1package generate 2 3import ( 4 "crypto/rand" 5 "crypto/rsa" 6 "crypto/sha256" 7 "crypto/tls" 8 "crypto/x509" 9 "crypto/x509/pkix" 10 "encoding/hex" 11 "encoding/pem" 12 "fmt" 13 "math/big" 14 "time" 15) 16 17// DefaultDomain Traefik domain for the default certificate. 18const DefaultDomain = "TRAEFIK DEFAULT CERT" 19 20// DefaultCertificate generates random TLS certificates. 21func DefaultCertificate() (*tls.Certificate, error) { 22 randomBytes := make([]byte, 100) 23 _, err := rand.Read(randomBytes) 24 if err != nil { 25 return nil, err 26 } 27 zBytes := sha256.Sum256(randomBytes) 28 z := hex.EncodeToString(zBytes[:sha256.Size]) 29 domain := fmt.Sprintf("%s.%s.traefik.default", z[:32], z[32:]) 30 31 certPEM, keyPEM, err := KeyPair(domain, time.Time{}) 32 if err != nil { 33 return nil, err 34 } 35 36 certificate, err := tls.X509KeyPair(certPEM, keyPEM) 37 if err != nil { 38 return nil, err 39 } 40 41 return &certificate, nil 42} 43 44// KeyPair generates cert and key files. 45func KeyPair(domain string, expiration time.Time) ([]byte, []byte, error) { 46 rsaPrivKey, err := rsa.GenerateKey(rand.Reader, 2048) 47 if err != nil { 48 return nil, nil, err 49 } 50 keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(rsaPrivKey)}) 51 52 certPEM, err := PemCert(rsaPrivKey, domain, expiration) 53 if err != nil { 54 return nil, nil, err 55 } 56 return certPEM, keyPEM, nil 57} 58 59// PemCert generates PEM cert file. 60func PemCert(privKey *rsa.PrivateKey, domain string, expiration time.Time) ([]byte, error) { 61 derBytes, err := derCert(privKey, expiration, domain) 62 if err != nil { 63 return nil, err 64 } 65 66 return pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes}), nil 67} 68 69func derCert(privKey *rsa.PrivateKey, expiration time.Time, domain string) ([]byte, error) { 70 serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) 71 serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) 72 if err != nil { 73 return nil, err 74 } 75 76 if expiration.IsZero() { 77 expiration = time.Now().Add(365 * (24 * time.Hour)) 78 } 79 80 template := x509.Certificate{ 81 SerialNumber: serialNumber, 82 Subject: pkix.Name{ 83 CommonName: DefaultDomain, 84 }, 85 NotBefore: time.Now(), 86 NotAfter: expiration, 87 88 KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageKeyAgreement | x509.KeyUsageDataEncipherment, 89 ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, 90 BasicConstraintsValid: true, 91 DNSNames: []string{domain}, 92 } 93 94 return x509.CreateCertificate(rand.Reader, &template, &template, &privKey.PublicKey, privKey) 95} 96