forked from mirror/pages-server
88 lines
2.3 KiB
Go
88 lines
2.3 KiB
Go
package certificates
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/rand"
|
|
"crypto/rsa"
|
|
"crypto/tls"
|
|
"crypto/x509"
|
|
"crypto/x509/pkix"
|
|
"encoding/pem"
|
|
"math/big"
|
|
"time"
|
|
|
|
"github.com/go-acme/lego/v4/certcrypto"
|
|
"github.com/go-acme/lego/v4/certificate"
|
|
"github.com/rs/zerolog/log"
|
|
|
|
"codeberg.org/codeberg/pages/server/database"
|
|
)
|
|
|
|
func mockCert(domain, msg, mainDomainSuffix string, keyDatabase database.CertDB) (*tls.Certificate, error) {
|
|
key, err := certcrypto.GeneratePrivateKey(certcrypto.RSA2048)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
template := x509.Certificate{
|
|
SerialNumber: big.NewInt(1),
|
|
Subject: pkix.Name{
|
|
CommonName: domain,
|
|
Organization: []string{"Codeberg Pages Error Certificate (couldn't obtain ACME certificate)"},
|
|
OrganizationalUnit: []string{
|
|
"Will not try again for 6 hours to avoid hitting rate limits for your domain.",
|
|
"Check https://docs.codeberg.org/codeberg-pages/troubleshooting/ for troubleshooting tips, and feel " +
|
|
"free to create an issue at https://codeberg.org/Codeberg/pages-server if you can't solve it.\n",
|
|
"Error message: " + msg,
|
|
},
|
|
},
|
|
|
|
// certificates younger than 7 days are renewed, so this enforces the cert to not be renewed for a 6 hours
|
|
NotAfter: time.Now().Add(time.Hour*24*7 + time.Hour*6),
|
|
NotBefore: time.Now(),
|
|
|
|
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
|
|
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
|
BasicConstraintsValid: true,
|
|
}
|
|
certBytes, err := x509.CreateCertificate(
|
|
rand.Reader,
|
|
&template,
|
|
&template,
|
|
&key.(*rsa.PrivateKey).PublicKey,
|
|
key,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
out := &bytes.Buffer{}
|
|
err = pem.Encode(out, &pem.Block{
|
|
Bytes: certBytes,
|
|
Type: "CERTIFICATE",
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
outBytes := out.Bytes()
|
|
res := &certificate.Resource{
|
|
PrivateKey: certcrypto.PEMEncode(key),
|
|
Certificate: outBytes,
|
|
IssuerCertificate: outBytes,
|
|
Domain: domain,
|
|
}
|
|
databaseName := domain
|
|
if domain == "*"+mainDomainSuffix || domain == mainDomainSuffix[1:] {
|
|
databaseName = mainDomainSuffix
|
|
}
|
|
if err := keyDatabase.Put(databaseName, res); err != nil {
|
|
log.Error().Err(err)
|
|
}
|
|
|
|
tlsCertificate, err := tls.X509KeyPair(res.Certificate, res.PrivateKey)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &tlsCertificate, nil
|
|
}
|