Skip to content

Commit

Permalink
Handle certificate generation with password for testing purpose (elas…
Browse files Browse the repository at this point in the history
…tic#5431)

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
  • Loading branch information
Sterchele Nicolas authored and Steffen Siering committed Nov 6, 2017
1 parent f122937 commit ac0d5e0
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 29 deletions.
9 changes: 4 additions & 5 deletions libbeat/outputs/logstash/logstash_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package logstash

import (
"fmt"
"net"
"os"
"testing"
"time"
Expand Down Expand Up @@ -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
Expand All @@ -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{}{
Expand Down
80 changes: 59 additions & 21 deletions libbeat/outputs/transport/transptest/testing.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -217,7 +212,6 @@ func GenCertsForIPIfMIssing(
SerialNumber: "23",
CommonName: "*",
},
IPAddresses: []net.IP{ip},

SignatureAlgorithm: x509.SHA512WithRSA,
PublicKeyAlgorithm: x509.ECDSA,
Expand All @@ -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
Expand All @@ -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 {
Expand All @@ -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
}
6 changes: 3 additions & 3 deletions libbeat/outputs/transport/transptest/testing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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"

Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit ac0d5e0

Please sign in to comment.