v0.25.0 netacl and fixes
Test / test (push) Canceled after 0s
Test / e2e (push) Canceled after 0s

This commit is contained in:
lixen committed 2026-10-04 23:43:52 -04:00
1 parent 9e86d7999d
commit 4af072f4e5
30 files changed
+918 -228

No files matched your search

+12
View File
@@ -216,6 +216,7 @@ type TCPChainSourceOptions struct {
HelloTimeoutMS int64 `toml:"hello_timeout_ms"` // preamble deadline
TrustNode bool `toml:"trust_node"` // false: force node label from remote address
Auth *AuthOptions `toml:"auth"`
ACL *ACLOptions `toml:"acl"`
}
// HTTPChainSourceOptions defines settings for a stdlib HTTP listener ingesting
@@ -230,6 +231,7 @@ type HTTPChainSourceOptions struct {
ReadTimeoutMS int64 `toml:"read_timeout_ms"` // full request read deadline
TrustNode bool `toml:"trust_node"` // false: force node label from remote address
Auth *AuthOptions `toml:"auth"`
ACL *ACLOptions `toml:"acl"`
}
// --- Sink Options ---
@@ -277,6 +279,7 @@ type TCPSinkOptions struct {
KeepAlivePeriodMS int64 `toml:"keep_alive_period_ms"`
MaxConnections int64 `toml:"max_connections"` // 0 = unlimited
Auth *AuthOptions `toml:"auth"`
ACL *ACLOptions `toml:"acl"`
}
// HTTPSinkOptions defines settings for an HTTP SSE server sink
@@ -293,6 +296,7 @@ type HTTPSinkOptions struct {
LoginPage bool `toml:"login_page"` // GET /auth/login, needs auth.trusted_proxies
ViewerPage bool `toml:"viewer_page"` // GET /auth/view, needs login_page
Auth *AuthOptions `toml:"auth"`
ACL *ACLOptions `toml:"acl"`
}
// TCPChainSinkOptions defines settings for a stdlib TCP client forwarding
@@ -369,6 +373,14 @@ type AuthOptions struct {
PasswordFile string `toml:"password_file"`
}
// ACLOptions is a listener's address rules, entries being addresses or CIDRs:
// deny wins, then a set allow list admits only its entries. Validation is in
// internal/netacl.
type ACLOptions struct {
Allow []string `toml:"allow"`
Deny []string `toml:"deny"`
}
// --- TLS Options ---
// TLSOptions is one shape for both roles. Listeners present cert_file and
+19 -7
View File
@@ -40,6 +40,10 @@ var (
{Name: "issuer_key", Help: "CA key file, for tls=issuer"},
{Name: "hosts", List: true, Help: "names and addresses, beyond this host's, of a self or issuer certificate; ',' between them"},
}
aclParams = []PresetParam{
{Name: "allow", List: true, Help: "addresses or CIDRs that may connect, of listen's family; default: all; ',' between them"},
{Name: "deny", List: true, Help: "addresses or CIDRs refused, allow or not; ',' between them"},
}
transportParam = PresetParam{Name: "transport", Default: "tcp", Help: "tcp|http: tcp_chain or http_chain"}
)
@@ -60,13 +64,13 @@ var presets = []Preset{
return nil
}},
{"serve", "Serve files or standard input live: a browser viewer at /, SSE at /stream",
append([]PresetParam{pathParam, fromParam, formatParam("json"),
slices.Concat([]PresetParam{pathParam, fromParam, formatParam("json"),
{Name: "listen", Default: "127.0.0.1:8080", Help: "HOST:PORT; [IPV6]:PORT"},
{Name: "tls", Default: "off", Help: "off|self|issuer|files: a certificate made at startup (self-signed or from issuer_*), or files"},
{Name: "users", Help: "credentials file (lw auth add-user): readers log in with SCRAM"},
{Name: "proxy", List: true, Help: "addresses or CIDRs of the TLS-terminating proxies browsers come through; ',' between them"},
{Name: "viewer", Default: "false", Help: "true: the login page and viewer for users, behind proxy; without users the viewer is always on"},
}, tlsParams...),
}, aclParams, tlsParams),
func(p *PipelineConfig, v map[string]string) error {
p.PluginSources = pathOrStdin(v)
sink, err := listener(v, "off")
@@ -145,7 +149,7 @@ var presets = []Preset{
return nil
}},
{"aggregator", "Receive from edges over TLS, authenticated, to files or standard output",
append([]PresetParam{
slices.Concat([]PresetParam{
{Name: "listen", Default: "0.0.0.0:9000", Help: "HOST:PORT; [IPV6]:PORT; [::] for IPv6 only"},
transportParam,
{Name: "tls", Default: "self", Help: "self|issuer|files: a certificate made at startup (self-signed or from issuer_*), or files"},
@@ -153,7 +157,7 @@ var presets = []Preset{
{Name: "client_ca", Help: "CA file that verifies edge certificates (mTLS)"},
{Name: "out", Help: "directory for the received entries; default: standard output"},
formatParam("json"),
}, tlsParams...),
}, aclParams, tlsParams),
func(p *PipelineConfig, v map[string]string) error {
typ, err := chainType(v["transport"])
if err != nil {
@@ -268,14 +272,22 @@ var tlsModes = map[string]struct {
"files": {needs: map[string]string{"cert": "cert_file", "key": "key_file"}},
}
// listener starts a listening plugin's options: host, port and tls, whose
// mode decides which certificate keys apply.
// listener starts a listening plugin's options: host, port, acl and tls,
// whose mode decides which certificate keys apply.
func listener(v map[string]string, def string) (map[string]any, error) {
host, port, err := splitAddr("listen", v["listen"])
if err != nil {
return nil, err
}
opts := map[string]any{"host": host, "port": port}
opts, acl := map[string]any{"host": host, "port": port}, map[string]any{}
for _, k := range []string{"allow", "deny"} {
if v[k] != "" {
acl[k] = list(v[k])
}
}
if len(acl) > 0 {
opts["acl"] = acl
}
mode := cmp.Or(v["tls"], def)
m, ok := tlsModes[mode]
if !ok {