mirror of
https://github.com/jackc/pgx.git
synced 2025-04-27 13:14:32 +00:00
TLS setup and tests were rather finicky. It seems that openssl 3 encrypts certificates differently than older openssl and it does it in a way Go and/or pgx ssl handling code can't handle. It appears that this related to the use of a deprecated client certificate encryption system. This caused CI to be stuck on Ubuntu 20.04 and recently caused the contributing guide to fail to work on MacOS. Remove openssl from the test setup and replace it with a Go program that generates the certificates.
188 lines
4.2 KiB
Go
188 lines
4.2 KiB
Go
// Generates a CA, server certificate, and encrypted client certificate for testing pgx.
|
|
|
|
package main
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"crypto/rsa"
|
|
"crypto/x509"
|
|
"crypto/x509/pkix"
|
|
"encoding/pem"
|
|
"fmt"
|
|
"math/big"
|
|
"net"
|
|
"os"
|
|
"time"
|
|
)
|
|
|
|
func main() {
|
|
// Create the CA
|
|
ca := &x509.Certificate{
|
|
SerialNumber: big.NewInt(1),
|
|
Subject: pkix.Name{
|
|
CommonName: "pgx-root-ca",
|
|
},
|
|
NotBefore: time.Now(),
|
|
NotAfter: time.Now().AddDate(20, 0, 0),
|
|
IsCA: true,
|
|
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
|
|
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
|
|
BasicConstraintsValid: true,
|
|
}
|
|
|
|
caKey, err := rsa.GenerateKey(rand.Reader, 4096)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
caBytes, err := x509.CreateCertificate(rand.Reader, ca, ca, &caKey.PublicKey, caKey)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
err = writePrivateKey("ca.key", caKey)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
err = writeCertificate("ca.pem", caBytes)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
// Create a server certificate signed by the CA for localhost.
|
|
serverCert := &x509.Certificate{
|
|
SerialNumber: big.NewInt(2),
|
|
Subject: pkix.Name{
|
|
CommonName: "localhost",
|
|
},
|
|
DNSNames: []string{"localhost"},
|
|
IPAddresses: []net.IP{net.IPv4(127, 0, 0, 1), net.IPv6loopback},
|
|
NotBefore: time.Now(),
|
|
NotAfter: time.Now().AddDate(20, 0, 0),
|
|
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
|
|
KeyUsage: x509.KeyUsageDigitalSignature,
|
|
}
|
|
|
|
serverCertPrivKey, err := rsa.GenerateKey(rand.Reader, 2048)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
serverBytes, err := x509.CreateCertificate(rand.Reader, serverCert, ca, &serverCertPrivKey.PublicKey, caKey)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
err = writePrivateKey("localhost.key", serverCertPrivKey)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
err = writeCertificate("localhost.crt", serverBytes)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
// Create a client certificate signed by the CA and encrypted.
|
|
clientCert := &x509.Certificate{
|
|
SerialNumber: big.NewInt(3),
|
|
Subject: pkix.Name{
|
|
CommonName: "pgx_sslcert",
|
|
},
|
|
NotBefore: time.Now(),
|
|
NotAfter: time.Now().AddDate(20, 0, 0),
|
|
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
|
KeyUsage: x509.KeyUsageDigitalSignature,
|
|
}
|
|
|
|
clientCertPrivKey, err := rsa.GenerateKey(rand.Reader, 2048)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
clientBytes, err := x509.CreateCertificate(rand.Reader, clientCert, ca, &clientCertPrivKey.PublicKey, caKey)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
writeEncryptedPrivateKey("pgx_sslcert.key", clientCertPrivKey, "certpw")
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
writeCertificate("pgx_sslcert.crt", clientBytes)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
func writePrivateKey(path string, privateKey *rsa.PrivateKey) error {
|
|
file, err := os.Create(path)
|
|
if err != nil {
|
|
return fmt.Errorf("writePrivateKey: %w", err)
|
|
}
|
|
|
|
err = pem.Encode(file, &pem.Block{
|
|
Type: "RSA PRIVATE KEY",
|
|
Bytes: x509.MarshalPKCS1PrivateKey(privateKey),
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("writePrivateKey: %w", err)
|
|
}
|
|
|
|
err = file.Close()
|
|
if err != nil {
|
|
return fmt.Errorf("writePrivateKey: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func writeEncryptedPrivateKey(path string, privateKey *rsa.PrivateKey, password string) error {
|
|
file, err := os.Create(path)
|
|
if err != nil {
|
|
return fmt.Errorf("writeEncryptedPrivateKey: %w", err)
|
|
}
|
|
|
|
block, err := x509.EncryptPEMBlock(rand.Reader, "CERTIFICATE", x509.MarshalPKCS1PrivateKey(privateKey), []byte(password), x509.PEMCipher3DES)
|
|
if err != nil {
|
|
return fmt.Errorf("writeEncryptedPrivateKey: %w", err)
|
|
}
|
|
|
|
err = pem.Encode(file, block)
|
|
if err != nil {
|
|
return fmt.Errorf("writeEncryptedPrivateKey: %w", err)
|
|
}
|
|
|
|
err = file.Close()
|
|
if err != nil {
|
|
return fmt.Errorf("writeEncryptedPrivateKey: %w", err)
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
func writeCertificate(path string, certBytes []byte) error {
|
|
file, err := os.Create(path)
|
|
if err != nil {
|
|
return fmt.Errorf("writeCertificate: %w", err)
|
|
}
|
|
|
|
err = pem.Encode(file, &pem.Block{
|
|
Type: "CERTIFICATE",
|
|
Bytes: certBytes,
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("writeCertificate: %w", err)
|
|
}
|
|
|
|
err = file.Close()
|
|
if err != nil {
|
|
return fmt.Errorf("writeCertificate: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|