Skip to content

Commit c3cd076

Browse files
fix: fix http multipath bug
1 parent 9ab1481 commit c3cd076

File tree

3 files changed

+80
-1
lines changed

3 files changed

+80
-1
lines changed

config/config.go

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ package config
22

33
import (
44
"fmt"
5+
"strings"
56

67
"github.com/coder/serpent"
8+
"github.com/spf13/pflag"
79
)
810

911
// JailType represents the type of jail to use for network isolation
@@ -25,10 +27,38 @@ func NewJailTypeFromString(str string) (JailType, error) {
2527
}
2628
}
2729

30+
// AllowStringsArray is a custom type that implements pflag.Value to support
31+
// repeatable --allow flags without splitting on commas. This allows comma-separated
32+
// paths within a single allow rule (e.g., "path=/todos/1,/todos/2").
33+
type AllowStringsArray []string
34+
35+
var _ pflag.Value = (*AllowStringsArray)(nil)
36+
37+
// Set implements pflag.Value. It appends the value to the slice without splitting on commas.
38+
func (a *AllowStringsArray) Set(value string) error {
39+
*a = append(*a, value)
40+
return nil
41+
}
42+
43+
// String implements pflag.Value.
44+
func (a AllowStringsArray) String() string {
45+
return strings.Join(a, ",")
46+
}
47+
48+
// Type implements pflag.Value.
49+
func (a AllowStringsArray) Type() string {
50+
return "string"
51+
}
52+
53+
// Value returns the underlying slice of strings.
54+
func (a AllowStringsArray) Value() []string {
55+
return []string(a)
56+
}
57+
2858
type CliConfig struct {
2959
Config serpent.YAMLConfigPath `yaml:"-"`
3060
AllowListStrings serpent.StringArray `yaml:"allowlist"` // From config file
31-
AllowStrings serpent.StringArray `yaml:"-"` // From CLI flags only
61+
AllowStrings AllowStringsArray `yaml:"-"` // From CLI flags only
3262
LogLevel serpent.String `yaml:"log_level"`
3363
LogDir serpent.String `yaml:"log_dir"`
3464
ProxyPort serpent.Int64 `yaml:"proxy_port"`
@@ -38,6 +68,7 @@ type CliConfig struct {
3868
JailType serpent.String `yaml:"jail_type"`
3969
DisableAuditLogs serpent.Bool `yaml:"disable_audit_logs"`
4070
LogProxySocketPath serpent.String `yaml:"log_proxy_socket_path"`
71+
serpent.StringArray
4172
}
4273

4374
type AppConfig struct {

e2e_tests/nsjail/http_path_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,41 @@ func TestHTTPPathWildCardSymbol(t *testing.T) {
9797
nt.ExpectDeny("https://dev.coder.com/api")
9898
})
9999
}
100+
101+
func TestHTTPMultiPath(t *testing.T) {
102+
// Create and configure nsjail test
103+
nt := NewNSJailTest(t,
104+
WithNSJailAllowedRule("domain=jsonplaceholder.typicode.com path=/todos/1,/todos/2"),
105+
WithNSJailLogLevel("debug"),
106+
).
107+
Build().
108+
Start()
109+
110+
// Ensure cleanup
111+
defer nt.Stop()
112+
113+
// Test allowed HTTP request
114+
t.Run("HTTPRequestThroughBoundary", func(t *testing.T) {
115+
expectedResponse := `{
116+
"userId": 1,
117+
"id": 1,
118+
"title": "delectus aut autem",
119+
"completed": false
120+
}`
121+
nt.ExpectAllowed("http://jsonplaceholder.typicode.com/todos/1", expectedResponse)
122+
})
123+
124+
t.Run("HTTPRequestThroughBoundary", func(t *testing.T) {
125+
expectedResponse := `{
126+
"userId": 1,
127+
"id": 2,
128+
"title": "quis ut nam facilis et officia qui",
129+
"completed": false
130+
}`
131+
nt.ExpectAllowed("http://jsonplaceholder.typicode.com/todos/2", expectedResponse)
132+
})
133+
134+
t.Run("HTTPRequestThroughBoundary", func(t *testing.T) {
135+
nt.ExpectDeny("http://jsonplaceholder.typicode.com/todos/3")
136+
})
137+
}

rulesengine/rules_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -997,6 +997,16 @@ func TestParseAllowRule(t *testing.T) {
997997
expectedRule: Rule{},
998998
expectError: true,
999999
},
1000+
{
1001+
name: "multipath",
1002+
input: "domain=jsonplaceholder.typicode.com path=/api/v1,/api/v2",
1003+
expectedRule: Rule{
1004+
Raw: "domain=jsonplaceholder.typicode.com path=/api/v1,/api/v2",
1005+
PathPattern: [][]string{{"api", "v1"}, {"api", "v2"}},
1006+
HostPattern: []string{"jsonplaceholder", "typicode", "com"},
1007+
},
1008+
expectError: false,
1009+
},
10001010
}
10011011

10021012
for _, tt := range tests {

0 commit comments

Comments
 (0)