Skip to content

Commit 3c5b375

Browse files
Add tlscommon and httpcommon diagnostics hooks (#3587)
Add custom hooks to use diag hooks added in elastic/elastic-agent-libs#207 to provide additional files that contain information about the TLS certs used by the server's API, TLS infomation used when connecting to elasticsearch, and a full trace to each specified elasticsearch host.
1 parent a0090d3 commit 3c5b375

File tree

7 files changed

+146
-2
lines changed

7 files changed

+146
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Kind can be one of:
2+
# - breaking-change: a change to previously-documented behavior
3+
# - deprecation: functionality that is being removed in a later release
4+
# - bug-fix: fixes a problem in a previous version
5+
# - enhancement: extends functionality but does not break or fix existing behavior
6+
# - feature: new functionality
7+
# - known-issue: problems that we are aware of in a given version
8+
# - security: impacts on the security of a product or a user’s deployment.
9+
# - upgrade: important information for someone upgrading from a prior version
10+
# - other: does not fit into any of the other categories
11+
kind: enhancement
12+
13+
# Change summary; a 80ish characters long description of the change.
14+
summary: Add tlscommon and httpcommon diagnostic information
15+
16+
# Long description; in case the summary is not enough to describe the change
17+
# this field accommodate a description without length limits.
18+
# NOTE: This field will be rendered only for breaking-change and known-issue kinds at the moment.
19+
description: |
20+
Add tlscommon and httpcommon hooks for fleet-server to add API and
21+
output TLS diagnostics files when diagnostics are collected as well as
22+
an httpcommon diagnostics trace for fleet-server's connection to
23+
Elasticsearch.
24+
25+
# Affected component; a word indicating the component this changeset affects.
26+
component:
27+
28+
# PR URL; optional; the PR number that added the changeset.
29+
# If not present is automatically filled by the tooling finding the PR where this changelog fragment has been added.
30+
# NOTE: the tooling supports backports, so it's able to fill the original PR number instead of the backport PR number.
31+
# Please provide it if you are adding a fragment for a different PR.
32+
pr: https://github.com/elastic/fleet-server/pull/3587
33+
34+
# Issue URL; optional; the GitHub issue related to this changeset (either closes or is part of).
35+
# If not present is automatically filled by the tooling with the issue linked to the PR number.
36+
#issue: https://github.com/owner/repo/1234

internal/pkg/api/openapi.gen.go

+2-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/pkg/config/output.go

+49
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
package config
66

77
import (
8+
"bytes"
9+
"context"
810
"fmt"
911
"net"
1012
"net/http"
@@ -16,8 +18,10 @@ import (
1618
"time"
1719

1820
urlutil "github.com/elastic/elastic-agent-libs/kibana"
21+
"github.com/elastic/elastic-agent-libs/transport/httpcommon"
1922
"github.com/elastic/elastic-agent-libs/transport/tlscommon"
2023
"github.com/elastic/go-elasticsearch/v8"
24+
"github.com/rs/zerolog"
2125
)
2226

2327
// The timeout would be driven by the server for long poll.
@@ -228,3 +232,48 @@ func makeURL(defaultScheme string, defaultPath string, rawURL string, defaultPor
228232
addr.Host = host + ":" + port
229233
return addr.String(), nil
230234
}
235+
236+
func (c *Elasticsearch) DiagRequests(ctx context.Context) []byte {
237+
pURL, err := httpcommon.NewProxyURIFromString(c.ProxyURL)
238+
if err != nil {
239+
zerolog.Ctx(ctx).Warn().Err(err).Msg("Unable to transform proxy_url to url.URL")
240+
}
241+
settings := httpcommon.HTTPTransportSettings{
242+
TLS: c.TLS,
243+
Timeout: c.Timeout,
244+
Proxy: httpcommon.HTTPClientProxySettings{
245+
Disable: c.ProxyDisable,
246+
URL: pURL,
247+
Headers: httpcommon.ProxyHeaders(c.ProxyHeaders),
248+
},
249+
}
250+
headers := http.Header{}
251+
for k, v := range c.Headers {
252+
headers.Set(k, v)
253+
}
254+
255+
reqs := make([]*http.Request, 0, len(c.Hosts))
256+
257+
var res bytes.Buffer
258+
for _, host := range c.Hosts {
259+
u, err := url.Parse(host)
260+
if err != nil {
261+
zerolog.Ctx(ctx).Warn().Err(err).Str("host", host).Msg("Unable to transform host to url.URL")
262+
res.WriteString(fmt.Sprintf("Unable to transform host %q to url.URL: %v\n", host, err))
263+
continue
264+
}
265+
if u.Scheme == "" {
266+
u.Scheme = c.Protocol
267+
}
268+
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil)
269+
if err != nil {
270+
zerolog.Ctx(ctx).Warn().Err(err).Str("host", host).Msg("Unable to create request to host")
271+
res.WriteString(fmt.Sprintf("Unable to create request to host %q: %v\n", host, err))
272+
continue
273+
}
274+
req.Header = headers.Clone()
275+
reqs = append(reqs, req)
276+
}
277+
res.Write(settings.DiagRequests(reqs)())
278+
return res.Bytes()
279+
}

internal/pkg/config/output_test.go

+18
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
package config
99

1010
import (
11+
"context"
1112
"crypto/tls"
1213
"net/http"
14+
"net/http/httptest"
1315
"os"
1416
"path/filepath"
1517
"testing"
@@ -382,3 +384,19 @@ func setTestEnv(t *testing.T, env map[string]string) {
382384
t.Setenv(k, v)
383385
}
384386
}
387+
388+
func Test_Elasticsearch_DiagRequests(t *testing.T) {
389+
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
390+
w.WriteHeader(http.StatusOK)
391+
}))
392+
defer srv.Close()
393+
ctx, cancel := context.WithCancel(context.Background())
394+
defer cancel()
395+
es := &Elasticsearch{}
396+
es.InitDefaults()
397+
es.Hosts = []string{srv.URL}
398+
399+
p := es.DiagRequests(ctx)
400+
require.NotEmpty(t, p)
401+
require.Contains(t, string(p), "request 0 successful.")
402+
}

internal/pkg/server/agent.go

+38
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,44 @@ func (a *Agent) Run(ctx context.Context) error {
115115
}
116116
return p
117117
})
118+
a.agent.RegisterDiagnosticHook("fleet-server api tls diag", "fleet-server's API TLS config", "fleet-server-api-tls.txt", "text/plain", func() []byte {
119+
if a.srv == nil {
120+
log.Warn().Msg("Diagnostics hook failure fleet-server is nil.")
121+
return []byte(`Diagnostics hook failure fleet-server is nil`)
122+
}
123+
cfg := a.srv.GetConfig()
124+
if cfg == nil || len(cfg.Inputs) == 0 {
125+
log.Warn().Msg("Diagnostics hook failure config is nil.")
126+
return []byte(`Diagnostics hook failure config is nil`)
127+
}
128+
return cfg.Inputs[0].Server.TLS.DiagCerts()()
129+
})
130+
a.agent.RegisterDiagnosticHook("fleet-server output tls diag", "fleet-server's output TLS config", "fleet-server-output-tls.txt", "text/plain", func() []byte {
131+
if a.srv == nil {
132+
log.Warn().Msg("Diagnostics hook failure fleet-server is nil.")
133+
return []byte(`Diagnostics hook failure fleet-server is nil`)
134+
}
135+
cfg := a.srv.GetConfig()
136+
if cfg == nil {
137+
log.Warn().Msg("Diagnostics hook failure config is nil.")
138+
return []byte(`Diagnostics hook failure config is nil`)
139+
}
140+
return cfg.Output.Elasticsearch.TLS.DiagCerts()()
141+
})
142+
a.agent.RegisterOptionalDiagnosticHook("CONN", "fleet-server output request diag", "fleet-server output request trace diagnostics", "fleet-server-output-request.txt", "text/plain", func() []byte {
143+
if a.srv == nil {
144+
log.Warn().Msg("Diagnostics hook failure fleet-server is nil.")
145+
return []byte(`Diagnostics hook failure fleet-server is nil`)
146+
}
147+
cfg := a.srv.GetConfig()
148+
if cfg == nil {
149+
log.Warn().Msg("Diagnostics hook failure config is nil.")
150+
return []byte(`Diagnostics hook failure config is nil`)
151+
}
152+
ctx, cancel := context.WithTimeout(ctx, time.Second*30) // TODO(michel-laterman): duration/timeout should be part of the diagnostics action from fleet-server (https://github.com/elastic/fleet-server/issues/3648) and the control protocol (https://github.com/elastic/elastic-agent-client/issues/113)
153+
defer cancel()
154+
return cfg.Output.Elasticsearch.DiagRequests(ctx)
155+
})
118156

119157
subCtx, subCanceller := context.WithCancel(ctx)
120158
defer subCanceller()

model/openapi.yml

+1
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,7 @@ components:
557557
type: string
558558
enum:
559559
- CPU
560+
- CONN
560561
actionPolicyReassign:
561562
description: The POLICY_REASSIGN action data.
562563
type: object

pkg/api/types.gen.go

+2-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)