Skip to content

Commit 6c2f5ca

Browse files
committed
Changes as per PR review comments
1 parent bcdcd99 commit 6c2f5ca

File tree

12 files changed

+89
-116
lines changed

12 files changed

+89
-116
lines changed

api/grpc/mpi/v1/command.pb.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/grpc/mpi/v1/command.proto

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ message APIDetails {
352352
string location = 1;
353353
// the API listen directive
354354
string listen = 2;
355-
// the API Ca directive
355+
// the API CA file path
356356
string Ca = 3;
357357
}
358358

docs/proto/protos.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -678,7 +678,7 @@ Perform an associated API action on an instance
678678
| ----- | ---- | ----- | ----------- |
679679
| location | [string](#string) | | the API location directive |
680680
| listen | [string](#string) | | the API listen directive |
681-
| Ca | [string](#string) | | the API Ca directive |
681+
| Ca | [string](#string) | | the API CA file path |
682682

683683

684684

internal/collector/nginxossreceiver/internal/scraper/stubstatus/stub_status_scraper.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,11 @@ func (s *NginxStubStatusScraper) Start(_ context.Context, _ component.Host) erro
6868
httpClient := http.DefaultClient
6969
caCertLocation := s.cfg.APIDetails.Ca
7070
if caCertLocation != "" {
71-
s.settings.Logger.Debug("Reading from Location for Ca Cert : ", zap.Any(caCertLocation, caCertLocation))
71+
s.settings.Logger.Debug("Reading CA certificate", zap.Any("file_path", caCertLocation))
7272
caCert, err := os.ReadFile(caCertLocation)
7373
if err != nil {
74-
s.settings.Logger.Error("Error starting NGINX stub scraper. "+
75-
"Failed to read CA certificate : ", zap.Error(err))
74+
s.settings.Logger.Error("Error starting NGINX stub status scraper. "+
75+
"Failed to read CA certificate", zap.Error(err))
7676

7777
return nil
7878
}

internal/collector/nginxossreceiver/internal/scraper/stubstatus/stub_status_scraper_tls_test.go

Lines changed: 63 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,13 @@ package stubstatus
77

88
import (
99
"context"
10-
"crypto/rand"
11-
"crypto/rsa"
1210
"crypto/tls"
1311
"crypto/x509"
14-
"crypto/x509/pkix"
15-
"encoding/pem"
16-
"math/big"
1712
"net"
1813
"net/http"
1914
"net/http/httptest"
2015
"os"
21-
"path/filepath"
2216
"testing"
23-
"time"
2417

2518
"github.com/stretchr/testify/assert"
2619
"github.com/stretchr/testify/require"
@@ -29,71 +22,39 @@ import (
2922
"go.opentelemetry.io/collector/receiver/receivertest"
3023

3124
"github.com/nginx/agent/v3/internal/collector/nginxossreceiver/internal/config"
25+
"github.com/nginx/agent/v3/test/helpers"
3226
)
3327

3428
func TestStubStatusScraperTLS(t *testing.T) {
35-
// Create a test CA certificate and key
36-
ca := &x509.Certificate{
37-
SerialNumber: big.NewInt(1),
38-
Subject: pkix.Name{
39-
Organization: []string{"NGINX Agent Test CA"},
40-
},
41-
NotBefore: time.Now(),
42-
NotAfter: time.Now().AddDate(10, 0, 0),
43-
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageDigitalSignature,
44-
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
45-
BasicConstraintsValid: true,
46-
IsCA: true,
47-
}
48-
49-
caPrivKey, caPrivKeyErr := rsa.GenerateKey(rand.Reader, 2048)
50-
require.NoError(t, caPrivKeyErr)
51-
52-
caBytes, caBytesErr := x509.CreateCertificate(rand.Reader, ca, ca, &caPrivKey.PublicKey, caPrivKey)
53-
require.NoError(t, caBytesErr)
54-
55-
// Create a test server certificate signed by the CA
56-
cert := &x509.Certificate{
57-
SerialNumber: big.NewInt(2),
58-
Subject: pkix.Name{
59-
Organization: []string{"NGINX Agent Test"},
60-
},
61-
NotBefore: time.Now(),
62-
NotAfter: time.Now().AddDate(10, 0, 0),
63-
SubjectKeyId: []byte{1, 2, 3, 4, 6},
64-
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
65-
KeyUsage: x509.KeyUsageDigitalSignature,
66-
IPAddresses: []net.IP{net.IPv4(127, 0, 0, 1)},
67-
DNSNames: []string{"localhost"},
68-
}
69-
70-
certPrivKey, certPrivKeyErr := rsa.GenerateKey(rand.Reader, 2048)
71-
require.NoError(t, certPrivKeyErr)
72-
73-
certBytes, certBytesErr := x509.CreateCertificate(rand.Reader, cert, ca, &certPrivKey.PublicKey, caPrivKey)
74-
require.NoError(t, certBytesErr)
29+
// Generate self-signed certificate using helper
30+
keyBytes, certBytes := helpers.GenerateSelfSignedCert(t)
7531

7632
// Create a temporary directory for test files
7733
tempDir := t.TempDir()
7834

79-
// Save CA certificate to a file
80-
caFile := filepath.Join(tempDir, "ca.crt")
81-
caPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: caBytes})
82-
writeErr := os.WriteFile(caFile, caPEM, 0o600)
83-
require.NoError(t, writeErr)
35+
// Save certificate to a file
36+
certFile := helpers.WriteCertFiles(t, tempDir, helpers.Cert{
37+
Name: "server.crt",
38+
Type: "CERTIFICATE",
39+
Contents: certBytes,
40+
})
41+
42+
// Parse the private key
43+
key, err := x509.ParsePKCS1PrivateKey(keyBytes)
44+
require.NoError(t, err)
45+
46+
// Create a TLS config with our self-signed certificate
47+
tlsCert := tls.Certificate{
48+
Certificate: [][]byte{certBytes},
49+
PrivateKey: key,
50+
}
8451

85-
// Create a TLS config for the server
8652
serverTLSConfig := &tls.Config{
87-
MinVersion: tls.VersionTLS13,
88-
Certificates: []tls.Certificate{
89-
{
90-
Certificate: [][]byte{certBytes},
91-
PrivateKey: certPrivKey,
92-
},
93-
},
53+
MinVersion: tls.VersionTLS13,
54+
Certificates: []tls.Certificate{tlsCert},
9455
}
9556

96-
// Create a test server with TLS
57+
// Create a test server with our custom TLS config
9758
server := httptest.NewUnstartedServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
9859
if req.URL.Path == "/status" {
9960
rw.WriteHeader(http.StatusOK)
@@ -112,56 +73,65 @@ Reading: 6 Writing: 179 Waiting: 106
11273
server.StartTLS()
11374
defer server.Close()
11475

115-
// Test with TLS configuration
116-
t.Run("with TLS CA", func(t *testing.T) {
76+
// Test with TLS configuration using our self-signed certificate
77+
t.Run("with self-signed TLS", func(t *testing.T) {
11778
cfg, ok := config.CreateDefaultConfig().(*config.Config)
11879
require.True(t, ok)
11980

12081
cfg.APIDetails.URL = server.URL + "/status"
121-
cfg.APIDetails.Ca = caFile
82+
// Use the self-signed certificate for verification
83+
cfg.APIDetails.Ca = certFile
12284

12385
scraper := NewScraper(receivertest.NewNopSettings(component.Type{}), cfg)
12486

125-
err := scraper.Start(context.Background(), componenttest.NewNopHost())
126-
require.NoError(t, err)
87+
startErr := scraper.Start(context.Background(), componenttest.NewNopHost())
88+
require.NoError(t, startErr)
12789

12890
_, err = scraper.Scrape(context.Background())
129-
assert.NoError(t, err)
91+
assert.NoError(t, err, "Scraping with self-signed certificate should succeed")
13092
})
13193
}
13294

13395
func TestStubStatusScraperUnixSocket(t *testing.T) {
134-
// Use a shorter path for the socket to avoid path length issues
135-
socketPath := filepath.Join(os.TempDir(), "test-nginx.sock")
136-
// Clean up the socket file after the test
137-
t.Cleanup(func() { os.Remove(socketPath) })
138-
139-
// Create a Unix domain socket listener
140-
listener, listenErr := net.Listen("unix", socketPath)
141-
require.NoError(t, listenErr)
142-
defer listener.Close()
143-
144-
// Start a simple HTTP server on the Unix socket
145-
server := &http.Server{
146-
Handler: http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
147-
if req.URL.Path == "/status" {
148-
rw.WriteHeader(http.StatusOK)
149-
_, _ = rw.Write([]byte(`Active connections: 291
96+
// Create a test server with a Unix domain socket
97+
handler := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
98+
if req.URL.Path == "/status" {
99+
rw.WriteHeader(http.StatusOK)
100+
_, _ = rw.Write([]byte(`Active connections: 291
150101
server accepts handled requests
151102
16630948 16630946 31070465
152103
Reading: 6 Writing: 179 Waiting: 106
153104
`))
154105

155-
return
156-
}
157-
rw.WriteHeader(http.StatusNotFound)
158-
}),
106+
return
107+
}
108+
rw.WriteHeader(http.StatusNotFound)
109+
})
110+
111+
// Create a socket file in a temporary directory with a shorter path
112+
socketPath := "/tmp/nginx-test.sock"
113+
114+
// Clean up any existing socket file
115+
os.Remove(socketPath)
116+
117+
// Create a listener for the Unix socket
118+
listener, err := net.Listen("unix", socketPath)
119+
require.NoError(t, err, "Failed to create Unix socket listener")
120+
121+
// Create a test server with our custom listener
122+
server := &httptest.Server{
123+
Listener: listener,
124+
Config: &http.Server{Handler: handler},
159125
}
160126

161-
go func() {
162-
_ = server.Serve(listener)
163-
}()
164-
defer server.Close()
127+
// Start the server
128+
server.Start()
129+
130+
// Ensure cleanup of the socket file
131+
t.Cleanup(func() {
132+
server.Close()
133+
os.Remove(socketPath)
134+
})
165135

166136
// Test with Unix socket
167137
t.Run("with Unix socket", func(t *testing.T) {
@@ -173,8 +143,8 @@ Reading: 6 Writing: 179 Waiting: 106
173143

174144
scraper := NewScraper(receivertest.NewNopSettings(component.Type{}), cfg)
175145

176-
err := scraper.Start(context.Background(), componenttest.NewNopHost())
177-
require.NoError(t, err)
146+
startErr := scraper.Start(context.Background(), componenttest.NewNopHost())
147+
require.NoError(t, startErr)
178148

179149
_, err = scraper.Scrape(context.Background())
180150
assert.NoError(t, err)

internal/collector/nginxplusreceiver/scraper.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,12 @@ func (nps *NginxPlusScraper) Start(_ context.Context, _ component.Host) error {
8787
httpClient := http.DefaultClient
8888
caCertLocation := nps.cfg.APIDetails.Ca
8989
if caCertLocation != "" {
90-
nps.logger.Debug("Reading from Location for Ca Cert : ", zap.Any(caCertLocation, caCertLocation))
90+
nps.logger.Debug("Reading CA certificate", zap.Any("file_path", caCertLocation))
9191
caCert, err := os.ReadFile(caCertLocation)
9292
if err != nil {
93-
nps.logger.Error("Unable to start NGINX Plus scraper. Failed to read CA certificate: %v", zap.Error(err))
93+
nps.logger.Error("Error starting NGINX stub status scraper. "+
94+
"Failed to read CA certificate", zap.Error(err))
95+
9496
return err
9597
}
9698
caCertPool := x509.NewCertPool()

internal/config/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -792,7 +792,7 @@ func resolveDataPlaneConfig() *DataPlaneConfig {
792792
ReloadMonitoringPeriod: viperInstance.GetDuration(NginxReloadMonitoringPeriodKey),
793793
TreatWarningsAsErrors: viperInstance.GetBool(NginxTreatWarningsAsErrorsKey),
794794
ExcludeLogs: viperInstance.GetStringSlice(NginxExcludeLogsKey),
795-
ApiTls: TLSConfig{Ca: viperInstance.GetString(NginxApiTlsCa)},
795+
APITls: TLSConfig{Ca: viperInstance.GetString(NginxApiTlsCa)},
796796
},
797797
}
798798
}

internal/config/types.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ type (
6161
}
6262

6363
NginxDataPlaneConfig struct {
64-
ApiTls TLSConfig `yaml:"api_tls" mapstructure:"api_tls"`
64+
APITls TLSConfig `yaml:"api_tls" mapstructure:"api_tls"`
6565
ExcludeLogs []string `yaml:"exclude_logs" mapstructure:"exclude_logs"`
6666
ReloadMonitoringPeriod time.Duration `yaml:"reload_monitoring_period" mapstructure:"reload_monitoring_period"`
6767
TreatWarningsAsErrors bool `yaml:"treat_warnings_as_errors" mapstructure:"treat_warnings_as_errors"`

internal/datasource/config/nginx_config_parser.go

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,7 @@ func (ncp *NginxConfigParser) sslCert(ctx context.Context, file, rootDir string)
554554
func (ncp *NginxConfigParser) apiCallback(ctx context.Context, parent,
555555
current *crossplane.Directive, apiType string,
556556
) *model.APIDetails {
557-
urls := ncp.urlsForLocationDirectiveAPIDetails(parent, current, apiType)
557+
urls := ncp.urlsForLocationDirectiveAPIDetails(ctx, parent, current, apiType)
558558
if len(urls) > 0 {
559559
slog.DebugContext(ctx, fmt.Sprintf("%d potential %s urls", len(urls), apiType), "urls", urls)
560560
}
@@ -643,7 +643,7 @@ func (ncp *NginxConfigParser) pingAPIEndpoint(ctx context.Context, statusAPIDeta
643643

644644
// nolint: revive
645645
func (ncp *NginxConfigParser) urlsForLocationDirectiveAPIDetails(
646-
parent, current *crossplane.Directive,
646+
ctx context.Context, parent, current *crossplane.Directive,
647647
locationDirectiveName string,
648648
) []*model.APIDetails {
649649
var urls []*model.APIDetails
@@ -652,7 +652,7 @@ func (ncp *NginxConfigParser) urlsForLocationDirectiveAPIDetails(
652652
caCertLocation := ""
653653
// If SSl is enabled, check if CA cert is provided and the location is allowed
654654
if isSSL {
655-
caCertLocation = ncp.getCACertLocation()
655+
caCertLocation = ncp.getCACertLocation(ctx)
656656
}
657657
// process from the location block
658658
if current.Directive != locationDirective {
@@ -834,13 +834,12 @@ func (ncp *NginxConfigParser) socketClient(socketPath string) *http.Client {
834834
// prepareHTTPClient handles TLS config
835835
func (ncp *NginxConfigParser) prepareHTTPClient(ctx context.Context) (*http.Client, error) {
836836
httpClient := http.DefaultClient
837-
caCertLocation := ncp.agentConfig.DataPlaneConfig.Nginx.ApiTls.Ca
837+
caCertLocation := ncp.agentConfig.DataPlaneConfig.Nginx.APITls.Ca
838838

839839
if caCertLocation != "" && ncp.agentConfig.IsDirectoryAllowed(caCertLocation) {
840-
slog.DebugContext(ctx, "Reading from Location for Ca Cert : ", "cacertlocation", caCertLocation)
840+
slog.DebugContext(ctx, "Reading CA certificate", "file_path", caCertLocation)
841841
caCert, err := os.ReadFile(caCertLocation)
842842
if err != nil {
843-
slog.ErrorContext(ctx, "Failed to read CA certificate", "error", err)
844843
return nil, err
845844
}
846845
caCertPool := x509.NewCertPool()
@@ -860,12 +859,12 @@ func (ncp *NginxConfigParser) prepareHTTPClient(ctx context.Context) (*http.Clie
860859
}
861860

862861
// Populate the CA cert location based ondirectory allowance.
863-
func (ncp *NginxConfigParser) getCACertLocation() string {
864-
caCertLocation := ncp.agentConfig.DataPlaneConfig.Nginx.ApiTls.Ca
862+
func (ncp *NginxConfigParser) getCACertLocation(ctx context.Context) string {
863+
caCertLocation := ncp.agentConfig.DataPlaneConfig.Nginx.APITls.Ca
865864

866865
if caCertLocation != "" && !ncp.agentConfig.IsDirectoryAllowed(caCertLocation) {
867866
// If SSL is enabled but CA cert is provided and not allowed, treat it as if no CA cert
868-
slog.Warn("CA certificate location is not allowed, treating as if no CA cert provided.")
867+
slog.WarnContext(ctx, "CA certificate location is not allowed, treating as if no CA cert provided.")
869868
return ""
870869
}
871870

internal/datasource/config/nginx_config_parser_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,9 +1172,9 @@ func TestNginxConfigParser_urlsForLocationDirective(t *testing.T) {
11721172
assert.Len(t, xpConf.Parsed, 1)
11731173
err = ncp.crossplaneConfigTraverse(ctx, &xpConf,
11741174
func(ctx context.Context, parent, directive *crossplane.Directive) error {
1175-
_oss := ncp.urlsForLocationDirectiveAPIDetails(parent, directive,
1175+
_oss := ncp.urlsForLocationDirectiveAPIDetails(ctx, parent, directive,
11761176
stubStatusAPIDirective)
1177-
_plus := ncp.urlsForLocationDirectiveAPIDetails(parent, directive, plusAPIDirective)
1177+
_plus := ncp.urlsForLocationDirectiveAPIDetails(ctx, parent, directive, plusAPIDirective)
11781178
oss = append(oss, _oss...)
11791179
plus = append(plus, _plus...)
11801180

0 commit comments

Comments
 (0)