Skip to content

Commit 0e87a23

Browse files
authored
Add registry inspector to the HTTP server (#50207)
So, we can view and delete state entries via a Web interface.
1 parent 2428610 commit 0e87a23

21 files changed

Lines changed: 858 additions & 11 deletions

File tree

auditbeat/auditbeat.reference.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1808,6 +1808,30 @@ logging.files:
18081808
# mutex profile.
18091809
#http.pprof.mutex_profile_rate: 0
18101810

1811+
# WARNING: Internal debugging tool. Not a supported product feature.
1812+
#
1813+
# This setting is intended for use by Elastic engineers during development
1814+
# and troubleshooting. It has no authentication and may be changed or
1815+
# removed in any release without notice.
1816+
#
1817+
# When enabled, the following endpoints are exposed on the HTTP listener:
1818+
# GET /debug/state-inspector/states JSON dump of every state entry
1819+
# GET /debug/state-inspector/states.html Browser UI for the same
1820+
# DELETE /debug/state-inspector/states/<key> Permanently delete a state entry
1821+
#
1822+
# The state store may contain sensitive information such as source file
1823+
# paths, S3 object keys, AWS account identifiers, and source hostnames,
1824+
# all of which will be returned to any client that can reach the endpoint.
1825+
# Deleting state entries can cause duplicate processing, gaps in ingestion,
1826+
# or data loss; for active inputs, deletes may be transient and silently
1827+
# overwritten by the in-memory registrar.
1828+
#
1829+
# If you must enable this for troubleshooting, bind http.host to a loopback
1830+
# address (127.0.0.1), a Unix socket, or a Windows named pipe, and disable
1831+
# it again as soon as you are done.
1832+
#
1833+
#http.debug.state_inspector.enabled: false
1834+
18111835
# ============================== Process Security ==============================
18121836

18131837
# Enable or disable seccomp system call filtering on Linux. Default is enabled.

docs/reference/filebeat/http-endpoint.md

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,14 @@ The HTTP endpoint has the following configuration settings:
4646
`http.pprof.mutex_profile_rate`
4747
: (Optional) `mutex_profile_rate` controls the fraction of mutex contention events that are reported in the mutex profile available from `/debug/pprof/mutex`. On average 1/rate events are reported. To turn off profiling entirely, pass rate 0. The default value is 0.
4848

49+
`http.debug.state_inspector.enabled`
50+
: (Optional) Enable the state store inspector. **This is an internal debugging tool for Elastic engineers, not a supported product feature.** It has no authentication, may expose sensitive data (file paths, S3 object keys, AWS account identifiers, hostnames), and may be changed or removed in any release without notice. Deleting state entries can cause duplicate processing, gaps in ingestion, or data loss. If you must enable it, bind `http.host` to a loopback address, Unix socket, or Windows named pipe, and disable it again when done. Default is `false`. See [State Inspector](#state-inspector) for details.
51+
4952
This is the list of paths you can access. For pretty JSON output append `?pretty` to the URL.
5053

5154
You can query a unix socket using the `cURL` command and the `--unix-socket` flag.
5255

53-
```js
56+
```sh
5457
curl -XGET --unix-socket '/var/run/filebeat.sock' 'http:/stats/?pretty'
5558
```
5659

@@ -59,11 +62,11 @@ curl -XGET --unix-socket '/var/run/filebeat.sock' 'http:/stats/?pretty'
5962

6063
`/` provides basic info from the Filebeat. Example:
6164

62-
```js
65+
```sh
6366
curl -XGET 'localhost:5066/?pretty'
6467
```
6568

66-
```js subs=true
69+
```json subs=true
6770
{
6871
"beat": "filebeat",
6972
"hostname": "example.lan",
@@ -78,11 +81,11 @@ curl -XGET 'localhost:5066/?pretty'
7881

7982
`/stats` reports internal metrics. Example:
8083

81-
```js
84+
```sh
8285
curl -XGET 'localhost:5066/stats?pretty'
8386
```
8487

85-
```js
88+
```json
8689
{
8790
"beat": {
8891
"cpu": {
@@ -195,9 +198,37 @@ The actual output may contain more metrics specific to Filebeat
195198

196199
A request may optionally specify a `type` query parameter to request metrics for a specific type of input. And `pretty` may be included to have the returned JSON be pretty formatted.
197200

198-
```js
201+
```sh
199202
curl 'http://localhost:5066/inputs/'
200203
curl 'http://localhost:5066/inputs/?pretty'
201204
curl 'http://localhost:5066/inputs/?type=aws-s3&pretty'
202205
```
203206

207+
208+
## State Inspector [state-inspector]
209+
210+
```{applies_to}
211+
stack: preview 9.5
212+
```
213+
214+
::::{warning}
215+
**Internal debugging tool — not a supported product feature.** This is intended for use by Elastic engineers during development and troubleshooting. It has no authentication and may be changed or removed in any release without notice.
216+
217+
The state store may contain sensitive information such as source file paths, S3 object keys, AWS account identifiers, and source hostnames, all of which will be returned to any client that can reach the endpoint. Deleting state entries can cause duplicate processing, gaps in ingestion, or data loss; for active inputs, deletes may be transient and silently overwritten by the in-memory registrar.
218+
219+
If you must enable this for troubleshooting, bind `http.host` to a loopback address (`127.0.0.1`), a Unix socket, or a Windows named pipe, and disable it again as soon as you are done.
220+
::::
221+
222+
These endpoints are only available when `http.debug.state_inspector.enabled` is set to `true`. Filebeat exposes its input registry through this endpoint.
223+
224+
`/debug/state-inspector/states` returns a JSON array of all key-value pairs in the internal state store. `/debug/state-inspector/states.html` serves a browser UI for the same data.
225+
226+
```sh
227+
curl -XGET 'localhost:5066/debug/state-inspector/states?pretty'
228+
```
229+
230+
To permanently delete a specific state entry:
231+
232+
```sh
233+
curl -XDELETE 'localhost:5066/debug/state-inspector/states/<key>'
234+
```

filebeat/beater/filebeat.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,10 @@ func (fb *Filebeat) Run(b *beat.Beat) error {
325325
}
326326
defer stateStore.Close()
327327

328+
if b.API != nil {
329+
b.API.SetStateInspectorRegistry(stateStore.shared.registry, stateStore.storeName)
330+
}
331+
328332
// If notifier is set, configure the listener for output configuration
329333
// The notifier passes the elasticsearch output configuration down to the Elasticsearch backed state storage
330334
// in order to allow it fully configure

filebeat/filebeat.reference.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3078,6 +3078,30 @@ logging.files:
30783078
# mutex profile.
30793079
#http.pprof.mutex_profile_rate: 0
30803080

3081+
# WARNING: Internal debugging tool. Not a supported product feature.
3082+
#
3083+
# This setting is intended for use by Elastic engineers during development
3084+
# and troubleshooting. It has no authentication and may be changed or
3085+
# removed in any release without notice.
3086+
#
3087+
# When enabled, the following endpoints are exposed on the HTTP listener:
3088+
# GET /debug/state-inspector/states JSON dump of every state entry
3089+
# GET /debug/state-inspector/states.html Browser UI for the same
3090+
# DELETE /debug/state-inspector/states/<key> Permanently delete a state entry
3091+
#
3092+
# The state store may contain sensitive information such as source file
3093+
# paths, S3 object keys, AWS account identifiers, and source hostnames,
3094+
# all of which will be returned to any client that can reach the endpoint.
3095+
# Deleting state entries can cause duplicate processing, gaps in ingestion,
3096+
# or data loss; for active inputs, deletes may be transient and silently
3097+
# overwritten by the in-memory registrar.
3098+
#
3099+
# If you must enable this for troubleshooting, bind http.host to a loopback
3100+
# address (127.0.0.1), a Unix socket, or a Windows named pipe, and disable
3101+
# it again as soon as you are done.
3102+
#
3103+
#http.debug.state_inspector.enabled: false
3104+
30813105
# ============================== Process Security ==============================
30823106

30833107
# Enable or disable seccomp system call filtering on Linux. Default is enabled.

heartbeat/heartbeat.reference.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1891,6 +1891,30 @@ logging.files:
18911891
# mutex profile.
18921892
#http.pprof.mutex_profile_rate: 0
18931893

1894+
# WARNING: Internal debugging tool. Not a supported product feature.
1895+
#
1896+
# This setting is intended for use by Elastic engineers during development
1897+
# and troubleshooting. It has no authentication and may be changed or
1898+
# removed in any release without notice.
1899+
#
1900+
# When enabled, the following endpoints are exposed on the HTTP listener:
1901+
# GET /debug/state-inspector/states JSON dump of every state entry
1902+
# GET /debug/state-inspector/states.html Browser UI for the same
1903+
# DELETE /debug/state-inspector/states/<key> Permanently delete a state entry
1904+
#
1905+
# The state store may contain sensitive information such as source file
1906+
# paths, S3 object keys, AWS account identifiers, and source hostnames,
1907+
# all of which will be returned to any client that can reach the endpoint.
1908+
# Deleting state entries can cause duplicate processing, gaps in ingestion,
1909+
# or data loss; for active inputs, deletes may be transient and silently
1910+
# overwritten by the in-memory registrar.
1911+
#
1912+
# If you must enable this for troubleshooting, bind http.host to a loopback
1913+
# address (127.0.0.1), a Unix socket, or a Windows named pipe, and disable
1914+
# it again as soon as you are done.
1915+
#
1916+
#http.debug.state_inspector.enabled: false
1917+
18941918
# ============================== Process Security ==============================
18951919

18961920
# Enable or disable seccomp system call filtering on Linux. Default is enabled.

libbeat/_meta/config/http.reference.yml.tmpl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,27 @@
3838
# Controls the fraction of mutex contention events that are reported in the
3939
# mutex profile.
4040
#http.pprof.mutex_profile_rate: 0
41+
42+
# WARNING: Internal debugging tool. Not a supported product feature.
43+
#
44+
# This setting is intended for use by Elastic engineers during development
45+
# and troubleshooting. It has no authentication and may be changed or
46+
# removed in any release without notice.
47+
#
48+
# When enabled, the following endpoints are exposed on the HTTP listener:
49+
# GET /debug/state-inspector/states JSON dump of every state entry
50+
# GET /debug/state-inspector/states.html Browser UI for the same
51+
# DELETE /debug/state-inspector/states/<key> Permanently delete a state entry
52+
#
53+
# The state store may contain sensitive information such as source file
54+
# paths, S3 object keys, AWS account identifiers, and source hostnames,
55+
# all of which will be returned to any client that can reach the endpoint.
56+
# Deleting state entries can cause duplicate processing, gaps in ingestion,
57+
# or data loss; for active inputs, deletes may be transient and silently
58+
# overwritten by the in-memory registrar.
59+
#
60+
# If you must enable this for troubleshooting, bind http.host to a loopback
61+
# address (127.0.0.1), a Unix socket, or a Windows named pipe, and disable
62+
# it again as soon as you are done.
63+
#
64+
#http.debug.state_inspector.enabled: false

libbeat/api/config.go

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,24 @@ package api
1919

2020
import "os"
2121

22+
// StateInspectorConfig holds the configuration for the state store inspector.
23+
type StateInspectorConfig struct {
24+
Enabled bool `config:"enabled"`
25+
}
26+
27+
// DebugConfig holds the configuration for debugging endpoints.
28+
type DebugConfig struct {
29+
StateInspector StateInspectorConfig `config:"state_inspector"`
30+
}
31+
2232
// Config is the configuration for the API endpoint.
2333
type Config struct {
24-
Enabled bool `config:"enabled"`
25-
Host string `config:"host"`
26-
Port int `config:"port"`
27-
User string `config:"named_pipe.user"`
28-
SecurityDescriptor string `config:"named_pipe.security_descriptor"`
34+
Enabled bool `config:"enabled"`
35+
Host string `config:"host"`
36+
Port int `config:"port"`
37+
User string `config:"named_pipe.user"`
38+
SecurityDescriptor string `config:"named_pipe.security_descriptor"`
39+
Debug DebugConfig `config:"debug"`
2940
}
3041

3142
// DefaultConfig is the default configuration used by the API endpoint.

libbeat/api/server.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import (
2626
"strings"
2727
"sync"
2828

29+
"github.com/elastic/beats/v7/libbeat/statestore"
30+
"github.com/elastic/beats/v7/libbeat/statestore/inspector"
2931
"github.com/elastic/elastic-agent-libs/config"
3032
"github.com/elastic/elastic-agent-libs/logp"
3133
)
@@ -49,6 +51,7 @@ type Server struct {
4951
mutex sync.Mutex
5052
httpServer *http.Server
5153
state serverState
54+
inspector *inspector.Handler
5255
}
5356

5457
// New creates a new API Server with no routes attached.
@@ -150,6 +153,26 @@ func (s *Server) AttachHandler(route string, h http.Handler) (err error) {
150153
return nil
151154
}
152155

156+
// AttachStateInspector creates and registers the state store inspector
157+
// handler if enabled in config. Calling it more than once or when the
158+
// inspector is disabled is a no-op.
159+
func (s *Server) AttachStateInspector() error {
160+
if !s.config.Debug.StateInspector.Enabled || s.inspector != nil {
161+
return nil
162+
}
163+
s.inspector = inspector.New()
164+
return s.AttachHandler("/debug/state-inspector/", http.StripPrefix("/debug/state-inspector", s.inspector))
165+
}
166+
167+
// SetStateInspectorRegistry provides the backing registry and store name to
168+
// the state inspector. Each HTTP request will obtain its own Store instance
169+
// via registry.Get(name). This is a no-op when the inspector is not enabled.
170+
func (s *Server) SetStateInspectorRegistry(registry *statestore.Registry, name string) {
171+
if s.inspector != nil {
172+
s.inspector.SetRegistry(registry, name)
173+
}
174+
}
175+
153176
// Router returns the mux.Router that handles all request to the server.
154177
func (s *Server) Router() *http.ServeMux {
155178
return s.mux

libbeat/cmd/instance/beat.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,9 @@ func (b *Beat) launch(settings Settings, bt beat.Creator) error {
466466
return fmt.Errorf("failed to attach http handlers for pprof: %w", err)
467467
}
468468
}
469+
if err := b.API.AttachStateInspector(); err != nil {
470+
return fmt.Errorf("failed to attach state inspector: %w", err)
471+
}
469472
}
470473

471474
// Do not load seccomp for osquerybeat, it was disabled before V2 in the configuration file

0 commit comments

Comments
 (0)