mirror of
https://github.com/yusing/godoxy.git
synced 2026-03-17 23:03:49 +01:00
refactor(proxmox): add struct level validation for node configuration services and files
Add Validate() method to NodeConfig that implements the CustomValidator interface. The method checks all services and files for invalid shell metacharacters (&, $(), etc.) to prevent shell injection attacks. Testing: Added validation_test.go with 6 table-driven test cases covering valid inputs and various shell metacharacter injection attempts.
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
gperr "github.com/yusing/goutils/errs"
|
||||
"github.com/yusing/goutils/pool"
|
||||
)
|
||||
|
||||
@@ -25,6 +26,22 @@ type Node struct {
|
||||
// statsScriptInitErrs *xsync.Map[int, error]
|
||||
}
|
||||
|
||||
// Validate implements the serialization.CustomValidator interface.
|
||||
func (n *NodeConfig) Validate() gperr.Error {
|
||||
var errs gperr.Builder
|
||||
for i, service := range n.Services {
|
||||
if err := checkValidInput(service); err != nil {
|
||||
errs.AddSubjectf(err, "services[%d]", i)
|
||||
}
|
||||
}
|
||||
for i, file := range n.Files {
|
||||
if err := checkValidInput(file); err != nil {
|
||||
errs.AddSubjectf(err, "files[%d]", i)
|
||||
}
|
||||
}
|
||||
return errs.Error()
|
||||
}
|
||||
|
||||
var Nodes = pool.New[*Node]("proxmox_nodes")
|
||||
|
||||
func NewNode(client *Client, name, id string) *Node {
|
||||
|
||||
55
internal/proxmox/validation_test.go
Normal file
55
internal/proxmox/validation_test.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package proxmox
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/yusing/godoxy/internal/serialization"
|
||||
)
|
||||
|
||||
func TestValidateCommandArgs(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
yamlCfg string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "valid_services",
|
||||
yamlCfg: `services: ["foo", "bar"]`,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "invalid_services",
|
||||
yamlCfg: `services: ["foo", "bar & baz"]`,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "invalid_services_with_$(",
|
||||
yamlCfg: `services: ["foo", "bar & $(echo 'hello')"]`,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "valid_files",
|
||||
yamlCfg: `files: ["foo", "bar"]`,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "invalid_files",
|
||||
yamlCfg: `files: ["foo", "bar & baz"]`,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var cfg NodeConfig
|
||||
err := serialization.UnmarshalValidateYAML([]byte(tt.yamlCfg), &cfg)
|
||||
if tt.wantErr {
|
||||
require.Error(t, err)
|
||||
require.ErrorContains(t, err, "input contains invalid characters")
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user