aboutsummaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorkegsay <kegan@matrix.org>2022-02-01 16:36:17 +0000
committerGitHub <noreply@github.com>2022-02-01 16:36:17 +0000
commita09d71d231861f8825a4f8f1dfd79311c4c236a6 (patch)
tree23768a595cc4972ec63ddf74c66a2605fac61e74 /internal
parent9ada4578e36b367c53057c9ee32d044e2ba26395 (diff)
Support CA certificates in CI (#2136)
* Support CA setting in generate-keys * Set DNS names correctly * Use generate-config -server not sed
Diffstat (limited to 'internal')
-rw-r--r--internal/test/config.go93
1 files changed, 82 insertions, 11 deletions
diff --git a/internal/test/config.go b/internal/test/config.go
index bb2f8a4c..4fb6a946 100644
--- a/internal/test/config.go
+++ b/internal/test/config.go
@@ -20,6 +20,7 @@ import (
"crypto/x509"
"encoding/base64"
"encoding/pem"
+ "errors"
"fmt"
"io/ioutil"
"math/big"
@@ -158,11 +159,10 @@ func NewMatrixKey(matrixKeyPath string) (err error) {
const certificateDuration = time.Hour * 24 * 365 * 10
-// NewTLSKey generates a new RSA TLS key and certificate and writes it to a file.
-func NewTLSKey(tlsKeyPath, tlsCertPath string) error {
+func generateTLSTemplate(dnsNames []string) (*rsa.PrivateKey, *x509.Certificate, error) {
priv, err := rsa.GenerateKey(rand.Reader, 4096)
if err != nil {
- return err
+ return nil, nil, err
}
notBefore := time.Now()
@@ -170,7 +170,7 @@ func NewTLSKey(tlsKeyPath, tlsCertPath string) error {
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
- return err
+ return nil, nil, err
}
template := x509.Certificate{
@@ -180,20 +180,21 @@ func NewTLSKey(tlsKeyPath, tlsCertPath string) error {
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
BasicConstraintsValid: true,
+ DNSNames: dnsNames,
}
- derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
- if err != nil {
- return err
- }
+ return priv, &template, nil
+}
+
+func writeCertificate(tlsCertPath string, derBytes []byte) error {
certOut, err := os.Create(tlsCertPath)
if err != nil {
return err
}
defer certOut.Close() // nolint: errcheck
- if err = pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil {
- return err
- }
+ return pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
+}
+func writePrivateKey(tlsKeyPath string, priv *rsa.PrivateKey) error {
keyOut, err := os.OpenFile(tlsKeyPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
return err
@@ -205,3 +206,73 @@ func NewTLSKey(tlsKeyPath, tlsCertPath string) error {
})
return err
}
+
+// NewTLSKey generates a new RSA TLS key and certificate and writes it to a file.
+func NewTLSKey(tlsKeyPath, tlsCertPath string) error {
+ priv, template, err := generateTLSTemplate(nil)
+ if err != nil {
+ return err
+ }
+
+ // Self-signed certificate: template == parent
+ derBytes, err := x509.CreateCertificate(rand.Reader, template, template, &priv.PublicKey, priv)
+ if err != nil {
+ return err
+ }
+
+ if err = writeCertificate(tlsCertPath, derBytes); err != nil {
+ return err
+ }
+ return writePrivateKey(tlsKeyPath, priv)
+}
+
+func NewTLSKeyWithAuthority(serverName, tlsKeyPath, tlsCertPath, authorityKeyPath, authorityCertPath string) error {
+ priv, template, err := generateTLSTemplate([]string{serverName})
+ if err != nil {
+ return err
+ }
+
+ // load the authority key
+ dat, err := ioutil.ReadFile(authorityKeyPath)
+ if err != nil {
+ return err
+ }
+ block, _ := pem.Decode([]byte(dat))
+ if block == nil || block.Type != "RSA PRIVATE KEY" {
+ return errors.New("authority .key is not a valid pem encoded rsa private key")
+ }
+ authorityPriv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
+ if err != nil {
+ return err
+ }
+
+ // load the authority certificate
+ dat, err = ioutil.ReadFile(authorityCertPath)
+ if err != nil {
+ return err
+ }
+ block, _ = pem.Decode([]byte(dat))
+ if block == nil || block.Type != "CERTIFICATE" {
+ return errors.New("authority .crt is not a valid pem encoded x509 cert")
+ }
+ var caCerts []*x509.Certificate
+ caCerts, err = x509.ParseCertificates(block.Bytes)
+ if err != nil {
+ return err
+ }
+ if len(caCerts) != 1 {
+ return errors.New("authority .crt contains none or more than one cert")
+ }
+ authorityCert := caCerts[0]
+
+ // Sign the new certificate using the authority's key/cert
+ derBytes, err := x509.CreateCertificate(rand.Reader, template, authorityCert, &priv.PublicKey, authorityPriv)
+ if err != nil {
+ return err
+ }
+
+ if err = writeCertificate(tlsCertPath, derBytes); err != nil {
+ return err
+ }
+ return writePrivateKey(tlsKeyPath, priv)
+}