@@ -20,18 +20,24 @@ package apmservertest
20
20
import (
21
21
"bytes"
22
22
"context"
23
+ "crypto/ecdsa"
24
+ "crypto/elliptic"
25
+ "crypto/rand"
26
+ "crypto/sha256"
23
27
"crypto/tls"
24
28
"crypto/x509"
29
+ "crypto/x509/pkix"
25
30
"encoding/json"
31
+ "encoding/pem"
26
32
"errors"
27
33
"fmt"
28
34
"io"
35
+ "math/big"
29
36
"net"
30
37
"net/http"
31
38
"net/url"
32
39
"os"
33
40
"os/exec"
34
- "path/filepath"
35
41
"strings"
36
42
"sync"
37
43
"testing"
@@ -60,6 +66,11 @@ type Server struct {
60
66
// The temporary directory will be removed when the server is closed.
61
67
Dir string
62
68
69
+ // CertDir is the directory of the TLS certificates.
70
+ //
71
+ // If Dir is empty the current directory is used
72
+ CertDir string
73
+
63
74
// Log holds an optional io.Writer to which the process's Stderr will
64
75
// be written, in addition to being available through the Server.Logs
65
76
// field.
@@ -125,6 +136,7 @@ func NewServerTB(tb testing.TB, args ...string) *Server {
125
136
// will be written under apm-server/systemtest/logs/<test-name>/.
126
137
func NewUnstartedServerTB (tb testing.TB , args ... string ) * Server {
127
138
s := NewUnstartedServer (args ... )
139
+ s .CertDir = tb .TempDir ()
128
140
logfile := createLogfile (tb , "apm-server" )
129
141
s .Log = logfile
130
142
tb .Cleanup (func () {
@@ -253,14 +265,8 @@ func (s *Server) start(tls bool) error {
253
265
}
254
266
255
267
func (s * Server ) initTLS () (serverCertPath , serverKeyPath , caCertPath string , _ error ) {
256
- repoRoot , err := getRepoRoot ()
257
- if err != nil {
258
- panic (err )
259
- }
260
-
268
+ serverCertPath , serverKeyPath , err := generateCerts (s .CertDir , true , x509 .ExtKeyUsageServerAuth , "127.0.0.1" , "::1" )
261
269
// Load a self-signed server certificate for testing TLS encryption.
262
- serverCertPath = filepath .Join (repoRoot , "systemtest" , "apmservertest" , "cert.pem" )
263
- serverKeyPath = filepath .Join (repoRoot , "systemtest" , "apmservertest" , "key.pem" )
264
270
serverCertBytes , err := os .ReadFile (serverCertPath )
265
271
if err != nil {
266
272
return "" , "" , "" , err
@@ -270,9 +276,12 @@ func (s *Server) initTLS() (serverCertPath, serverKeyPath, caCertPath string, _
270
276
panic ("failed to add CA certificate to cert pool" )
271
277
}
272
278
279
+ clientCertPath , clientKeyPath , err := generateCerts (s .CertDir , false , x509 .ExtKeyUsageClientAuth , "" )
280
+ if err != nil {
281
+ return "" , "" , "" , err
282
+ }
283
+
273
284
// Load a self-signed client certificate for testing TLS client certificate auth.
274
- clientCertPath := filepath .Join (repoRoot , "systemtest" , "apmservertest" , "client_cert.pem" )
275
- clientKeyPath := filepath .Join (repoRoot , "systemtest" , "apmservertest" , "client_key.pem" )
276
285
clientCertBytes , err := os .ReadFile (clientCertPath )
277
286
if err != nil {
278
287
return "" , "" , "" , err
@@ -289,11 +298,83 @@ func (s *Server) initTLS() (serverCertPath, serverKeyPath, caCertPath string, _
289
298
s .TLS = & tls.Config {
290
299
Certificates : []tls.Certificate {clientCert },
291
300
RootCAs : certpool ,
292
- MinVersion : tls .VersionTLS12 ,
293
301
}
294
302
return serverCertPath , serverKeyPath , clientCertPath , nil
295
303
}
296
304
305
+ func generateCerts (dir string , ca bool , keyUsage x509.ExtKeyUsage , hosts ... string ) (string , string , error ) {
306
+ serialNumberLimit := new (big.Int ).Lsh (big .NewInt (1 ), 128 )
307
+ serialNumber , err := rand .Int (rand .Reader , serialNumberLimit )
308
+ if err != nil {
309
+ return "" , "" , fmt .Errorf ("Failed to generate serial number: %w" , err )
310
+ }
311
+ notBefore := time .Now ()
312
+ notAfter := notBefore .Add (24 * time .Hour )
313
+ template := x509.Certificate {
314
+ SerialNumber : serialNumber ,
315
+ Subject : pkix.Name {
316
+ Organization : []string {"Org" },
317
+ },
318
+ NotBefore : notBefore ,
319
+ NotAfter : notAfter ,
320
+
321
+ KeyUsage : x509 .KeyUsageDigitalSignature ,
322
+ ExtKeyUsage : []x509.ExtKeyUsage {keyUsage },
323
+ BasicConstraintsValid : true ,
324
+ }
325
+
326
+ for _ , h := range hosts {
327
+ if ip := net .ParseIP (h ); ip != nil {
328
+ template .IPAddresses = append (template .IPAddresses , ip )
329
+ }
330
+ }
331
+
332
+ if ca {
333
+ template .IsCA = true
334
+ template .KeyUsage |= x509 .KeyUsageCertSign
335
+ }
336
+
337
+ clientKey , err := ecdsa .GenerateKey (elliptic .P256 (), rand .Reader )
338
+ if err != nil {
339
+ return "" , "" , fmt .Errorf ("failed to generate client key: %w" , err )
340
+ }
341
+ privBytes , err := x509 .MarshalPKCS8PrivateKey (clientKey )
342
+ if err != nil {
343
+ return "" , "" , fmt .Errorf ("unable to marshal private key: %w" , err )
344
+ }
345
+
346
+ h := sha256 .Sum256 (privBytes )
347
+ template .SubjectKeyId = h [:]
348
+
349
+ derBytes , err := x509 .CreateCertificate (rand .Reader , & template , & template , clientKey .Public (), clientKey )
350
+ if err != nil {
351
+ return "" , "" , fmt .Errorf ("failed to create certificate: %w" , err )
352
+ }
353
+ certOut , err := os .CreateTemp (dir , "client_cert.pem" )
354
+ if err != nil {
355
+ return "" , "" , fmt .Errorf ("failed to open client_cert.pem for writing: %w" , err )
356
+ }
357
+ if err := pem .Encode (certOut , & pem.Block {Type : "CERTIFICATE" , Bytes : derBytes }); err != nil {
358
+ return "" , "" , fmt .Errorf ("failed to write data to client_cert.pem: %w" , err )
359
+ }
360
+ if err := certOut .Close (); err != nil {
361
+ return "" , "" , fmt .Errorf ("error closing client_cert.pem: %w" , err )
362
+ }
363
+
364
+ keyOut , err := os .CreateTemp (dir , "client_key.pem" )
365
+ if err != nil {
366
+ return "" , "" , fmt .Errorf ("failed to open client_key.pem for writing: %w" , err )
367
+ }
368
+ if err := pem .Encode (keyOut , & pem.Block {Type : "PRIVATE KEY" , Bytes : privBytes }); err != nil {
369
+ return "" , "" , fmt .Errorf ("failed to write data to client_key.pem: %w" , err )
370
+ }
371
+ if err := keyOut .Close (); err != nil {
372
+ return "" , "" , fmt .Errorf ("error closing client_key.pem: %w" , err )
373
+ }
374
+
375
+ return certOut .Name (), keyOut .Name (), nil
376
+ }
377
+
297
378
func (s * Server ) printCmdline (w io.Writer , args []string ) {
298
379
var buf bytes.Buffer
299
380
fmt .Fprint (& buf , "# Running apm-server\n " )
0 commit comments