From 421021fedd6d615a9c6087f164c3265831cb5692 Mon Sep 17 00:00:00 2001 From: Sterchele Nicolas Date: Mon, 23 Oct 2017 23:12:31 +0200 Subject: [PATCH] Handle certificate generation with password for testing purpose Change made on GenCertsForIPIfMIssing function: - Rename the function to GenCertForTestingPurpose - Replace ip parameter by host, can be an ip or a dns name - Add password parameter to generate encrypted private key --- libbeat/outputs/logstash/logstash_test.go | 9 +-- .../outputs/transport/transptest/testing.go | 80 ++++++++++++++----- .../transport/transptest/testing_test.go | 6 +- 3 files changed, 66 insertions(+), 29 deletions(-) diff --git a/libbeat/outputs/logstash/logstash_test.go b/libbeat/outputs/logstash/logstash_test.go index af753a2c507..a01707559cf 100644 --- a/libbeat/outputs/logstash/logstash_test.go +++ b/libbeat/outputs/logstash/logstash_test.go @@ -2,7 +2,6 @@ package logstash import ( "fmt" - "net" "os" "testing" "time" @@ -41,10 +40,10 @@ func TestLogstashTLS(t *testing.T) { enableLogging([]string{"*"}) certName := "ca_test" - ip := net.IP{127, 0, 0, 1} + ip := "127.0.0.1" timeout := 2 * time.Second - transptest.GenCertsForIPIfMIssing(t, ip, certName) + transptest.GenCertForTestingPurpose(t, ip, certName, "") server := transptest.NewMockServerTLS(t, timeout, certName, nil) // create lumberjack output client @@ -59,10 +58,10 @@ func TestLogstashTLS(t *testing.T) { func TestLogstashInvalidTLSInsecure(t *testing.T) { certName := "ca_invalid_test" - ip := net.IP{1, 2, 3, 4} + ip := "1.2.3.4" timeout := 2 * time.Second - transptest.GenCertsForIPIfMIssing(t, ip, certName) + transptest.GenCertForTestingPurpose(t, ip, certName, "") server := transptest.NewMockServerTLS(t, timeout, certName, nil) config := map[string]interface{}{ diff --git a/libbeat/outputs/transport/transptest/testing.go b/libbeat/outputs/transport/transptest/testing.go index d1589f1c8ee..795e3b4c96d 100644 --- a/libbeat/outputs/transport/transptest/testing.go +++ b/libbeat/outputs/transport/transptest/testing.go @@ -174,14 +174,9 @@ func connectTLS(timeout time.Duration, certName string) TransportFactory { } } -// genCertsIfMIssing generates a testing certificate for ip 127.0.0.1 for -// testing if certificate or key is missing. Generated is used for CA, -// client-auth and server-auth. Use only for testing. -func GenCertsForIPIfMIssing( - t *testing.T, - ip net.IP, - name string, -) error { +// GenCertForTestingPurpose generates a testing certificate. +// Generated is used for CA, client-auth and server-auth. Use only for testing. +func GenCertForTestingPurpose(t *testing.T, host, name, keyPassword string) error { capem := name + ".pem" cakey := name + ".key" @@ -217,7 +212,6 @@ func GenCertsForIPIfMIssing( SerialNumber: "23", CommonName: "*", }, - IPAddresses: []net.IP{ip}, SignatureAlgorithm: x509.SHA512WithRSA, PublicKeyAlgorithm: x509.ECDSA, @@ -233,12 +227,43 @@ func GenCertsForIPIfMIssing( x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, } + //Could be ip or dns format + ip := net.ParseIP(host) + if ip != nil { + caTemplate.IPAddresses = []net.IP{ip} + } else { + caTemplate.DNSNames = []string{host} + } - // generate keys - priv, err := rsa.GenerateKey(rand.Reader, 4096) + pemBlock, err := genPrivatePem(4096, keyPassword) if err != nil { t.Fatalf("failed to generate ca private key: %v", err) } + + // write key file + var keyOut *os.File + keyOut, err = os.OpenFile(cakey, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) + if err != nil { + t.Fatalf("failed to open key file for writing: %v", err) + } + pem.Encode(keyOut, pemBlock) + keyOut.Close() + + //Decrypt pem block to add it later to the certificate + if x509.IsEncryptedPEMBlock(pemBlock) { + pemBlock.Bytes, err = x509.DecryptPEMBlock(pemBlock, []byte(keyPassword)) + if err != nil { + t.Fatalf("failed to decrypt private key: %v", err) + } + } + + var priv *rsa.PrivateKey + priv, err = x509.ParsePKCS1PrivateKey(pemBlock.Bytes) + if err != nil { + t.Fatalf("failed to parse pemBlock to private key: %v", err) + return err + } + pub := &priv.PublicKey // generate certificate @@ -251,16 +276,6 @@ func GenCertsForIPIfMIssing( t.Fatalf("failed to generate ca certificate: %v", err) } - // write key file - keyOut, err := os.OpenFile(cakey, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) - if err != nil { - t.Fatalf("failed to open key file for writing: %v", err) - } - pem.Encode(keyOut, &pem.Block{ - Type: "RSA PRIVATE KEY", - Bytes: x509.MarshalPKCS1PrivateKey(priv)}) - keyOut.Close() - // write certificate certOut, err := os.Create(capem) if err != nil { @@ -271,3 +286,26 @@ func GenCertsForIPIfMIssing( return nil } + +func genPrivatePem(bits int, password string) (*pem.Block, error) { + //Generate private key + key, err := rsa.GenerateKey(rand.Reader, bits) + if err != nil { + return nil, err + } + + block := &pem.Block{ + Type: "RSA PRIVATE KEY", + Bytes: x509.MarshalPKCS1PrivateKey(key), + } + + //Encrypt pem block from the given password + if len(password) > 0 { + block, err = x509.EncryptPEMBlock(rand.Reader, block.Type, block.Bytes, []byte(password), x509.PEMCipherAES256) + if err != nil { + return nil, err + } + } + + return block, nil +} diff --git a/libbeat/outputs/transport/transptest/testing_test.go b/libbeat/outputs/transport/transptest/testing_test.go index 7db7cf36131..fdfced8faef 100644 --- a/libbeat/outputs/transport/transptest/testing_test.go +++ b/libbeat/outputs/transport/transptest/testing_test.go @@ -52,7 +52,7 @@ func TestTransportReconnectsOnConnect(t *testing.T) { certName := "ca_test" timeout := 2 * time.Second - GenCertsForIPIfMIssing(t, net.IP{127, 0, 0, 1}, certName) + GenCertForTestingPurpose(t, "127.0.0.1", certName, "") testServer(t, &config, func(t *testing.T, makeServer MockServerFactory, proxy *transport.ProxyConfig) { server := makeServer(t, timeout, certName, proxy) @@ -89,7 +89,7 @@ func TestTransportFailConnectUnknownAddress(t *testing.T) { defer l.Close() certName := "ca_test" - GenCertsForIPIfMIssing(t, net.IP{127, 0, 0, 1}, certName) + GenCertForTestingPurpose(t, "127.0.0.1", certName, "") invalidAddr := "invalid.dns.fqdn-unknown.invalid:100" @@ -123,7 +123,7 @@ func TestTransportClosedOnWriteReadError(t *testing.T) { certName := "ca_test" timeout := 2 * time.Second - GenCertsForIPIfMIssing(t, net.IP{127, 0, 0, 1}, certName) + GenCertForTestingPurpose(t, "127.0.0.1", certName, "") testServer(t, &config, func(t *testing.T, makeServer MockServerFactory, proxy *transport.ProxyConfig) { server := makeServer(t, timeout, certName, proxy)