-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbundle.go
More file actions
152 lines (134 loc) · 4.49 KB
/
bundle.go
File metadata and controls
152 lines (134 loc) · 4.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package hostlib
import (
"context"
"github.com/reglet-dev/reglet-host-sdk/netutil"
)
// HostFuncBundle is a pre-configured set of related host functions.
// Bundles allow registering multiple handlers at once for common use cases.
type HostFuncBundle interface {
// Handlers returns a map of handler names to ByteHandler functions.
Handlers() map[string]ByteHandler
}
// staticBundle implements HostFuncBundle with a fixed set of handlers.
type staticBundle struct {
handlers map[string]ByteHandler
}
func (b *staticBundle) Handlers() map[string]ByteHandler {
return b.handlers
}
// NetworkBundle returns a bundle with network-related host functions:
// dns_lookup, tcp_connect, http_request.
func NetworkBundle() HostFuncBundle {
return &staticBundle{
handlers: map[string]ByteHandler{
"dns_lookup": NewJSONHandler(func(ctx context.Context, req DNSLookupRequest) DNSLookupResponse { return PerformDNSLookup(ctx, req) }),
"tcp_connect": NewJSONHandler(func(ctx context.Context, req TCPConnectRequest) TCPConnectResponse {
return PerformTCPConnect(ctx, req)
}),
"http_request": NewJSONHandler(func(ctx context.Context, req HTTPRequest) HTTPResponse { return PerformHTTPRequest(ctx, req) }),
},
}
}
// ExecBundle returns a bundle with command execution host functions:
// exec_command.
func ExecBundle() HostFuncBundle {
return &staticBundle{
handlers: map[string]ByteHandler{
"exec_command": NewJSONHandler(func(ctx context.Context, req ExecCommandRequest) ExecCommandResponse {
return PerformExecCommand(ctx, req)
}),
},
}
}
// SMTPBundle returns a bundle with email-related host functions:
// smtp_connect.
func SMTPBundle() HostFuncBundle {
return &staticBundle{
handlers: map[string]ByteHandler{
"smtp_connect": NewJSONHandler(func(ctx context.Context, req SMTPConnectRequest) SMTPConnectResponse {
return PerformSMTPConnect(ctx, req)
}),
},
}
}
// SSRFCheckRequest is the request type for SSRF validation.
type SSRFCheckRequest struct {
// Address is the target address to validate (host:port format).
Address string `json:"address"`
}
// SSRFCheckResponse is the response type for SSRF validation.
type SSRFCheckResponse struct {
// Reason explains why the address was blocked (if not allowed).
Reason string `json:"reason,omitempty"`
// ResolvedIP is the resolved IP address if DNS resolution was performed.
ResolvedIP string `json:"resolved_ip,omitempty"`
// Allowed indicates whether the address is safe for outbound connections.
Allowed bool `json:"allowed"`
}
// NetfilterBundle returns a bundle with network security host functions:
// ssrf_check.
func NetfilterBundle() HostFuncBundle {
return &staticBundle{
handlers: map[string]ByteHandler{
"ssrf_check": NewJSONHandler(func(ctx context.Context, req SSRFCheckRequest) SSRFCheckResponse {
result := netutil.ValidateAddress(req.Address)
return SSRFCheckResponse{
Reason: result.Reason,
ResolvedIP: result.ResolvedIP,
Allowed: result.Allowed,
}
}),
},
}
}
// compositeBundle combines multiple bundles into one.
type compositeBundle struct {
bundles []HostFuncBundle
}
func (b *compositeBundle) Handlers() map[string]ByteHandler {
result := make(map[string]ByteHandler)
for _, bundle := range b.bundles {
for name, handler := range bundle.Handlers() {
result[name] = handler
}
}
return result
}
// AllBundles returns a bundle containing all built-in host functions.
// Includes: dns_lookup, tcp_connect, http_request, exec_command, smtp_send, ssrf_check.
func AllBundles() HostFuncBundle {
return &compositeBundle{
bundles: []HostFuncBundle{
NetworkBundle(),
ExecBundle(),
SMTPBundle(),
NetfilterBundle(),
},
}
}
// WithBundle registers all handlers from a bundle.
func WithBundle(bundle HostFuncBundle) RegistryOption {
return func(b *registryBuilder) {
for name, handler := range bundle.Handlers() {
if err := b.addHandler(name, handler); err != nil {
b.errors = append(b.errors, err)
}
}
}
}
// WithHandler registers a typed host function with automatic JSON handling.
// The handler will be wrapped with NewJSONHandler for JSON serialization.
//
// Example usage:
//
// WithHandler("custom_func", func(ctx context.Context, req MyRequest) MyResponse {
// return MyResponse{Result: req.Input}
// })
func WithHandler[Req any, Resp any](name string, fn HostFunc[Req, Resp]) RegistryOption {
return func(b *registryBuilder) {
handler := NewJSONHandler(fn)
if err := b.addHandler(name, handler); err != nil {
b.errors = append(b.errors, err)
}
}
}