github.com/bosssauce/ponzu@v0.11.1-0.20200102001432-9bc41b703131/system/tls/devcerts.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Modified 2016 by Steve Manuel, Boss Sauce Creative, LLC 6 // All modifications are relicensed under the same BSD license 7 // found in the LICENSE file. 8 9 // Generate a self-signed X.509 certificate for a TLS server. Outputs to 10 // 'devcerts/cert.pem' and 'devcerts/key.pem' and will overwrite existing files. 11 12 package tls 13 14 import ( 15 "crypto/ecdsa" 16 "crypto/rand" 17 "crypto/rsa" 18 "crypto/x509" 19 "crypto/x509/pkix" 20 "encoding/pem" 21 "fmt" 22 "log" 23 "math/big" 24 "net" 25 "os" 26 "path/filepath" 27 "time" 28 29 "github.com/ponzu-cms/ponzu/system/cfg" 30 31 "github.com/ponzu-cms/ponzu/system/db" 32 ) 33 34 func publicKey(priv interface{}) interface{} { 35 switch k := priv.(type) { 36 case *rsa.PrivateKey: 37 return &k.PublicKey 38 case *ecdsa.PrivateKey: 39 return &k.PublicKey 40 default: 41 return nil 42 } 43 } 44 45 func pemBlockForKey(priv interface{}) *pem.Block { 46 switch k := priv.(type) { 47 case *rsa.PrivateKey: 48 return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(k)} 49 case *ecdsa.PrivateKey: 50 b, err := x509.MarshalECPrivateKey(k) 51 if err != nil { 52 fmt.Fprintf(os.Stderr, "Unable to marshal ECDSA private key: %v", err) 53 os.Exit(2) 54 } 55 return &pem.Block{Type: "EC PRIVATE KEY", Bytes: b} 56 default: 57 return nil 58 } 59 } 60 61 func setupDev() { 62 var priv interface{} 63 var err error 64 65 priv, err = rsa.GenerateKey(rand.Reader, 2048) 66 67 if err != nil { 68 log.Fatalf("failed to generate private key: %s", err) 69 } 70 71 notBefore := time.Now() 72 notAfter := notBefore.Add(time.Hour * 24 * 30) // valid for 30 days 73 74 serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) 75 serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) 76 if err != nil { 77 log.Fatalf("failed to generate serial number: %s", err) 78 } 79 80 template := x509.Certificate{ 81 SerialNumber: serialNumber, 82 Subject: pkix.Name{ 83 Organization: []string{"Ponzu Dev Server"}, 84 }, 85 NotBefore: notBefore, 86 NotAfter: notAfter, 87 88 KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, 89 ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, 90 BasicConstraintsValid: true, 91 } 92 93 hosts := []string{"localhost", "0.0.0.0"} 94 domain := db.ConfigCache("domain").(string) 95 if domain != "" { 96 hosts = append(hosts, domain) 97 } 98 99 for _, h := range hosts { 100 if ip := net.ParseIP(h); ip != nil { 101 template.IPAddresses = append(template.IPAddresses, ip) 102 } else { 103 template.DNSNames = append(template.DNSNames, h) 104 } 105 } 106 107 // make all certs CA 108 template.IsCA = true 109 template.KeyUsage |= x509.KeyUsageCertSign 110 111 derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv) 112 if err != nil { 113 log.Fatalln("Failed to create certificate:", err) 114 } 115 116 // overwrite/create directory for devcerts 117 118 vendorTLSPath := cfg.TlsDir() 119 devcertsPath := filepath.Join(vendorTLSPath, "devcerts") 120 121 // clear all old certs if found 122 err = os.RemoveAll(devcertsPath) 123 if err != nil { 124 log.Fatalln("Failed to remove old files from dev certificate directory:", err) 125 } 126 127 err = os.MkdirAll(devcertsPath, os.ModeDir|os.ModePerm) 128 if err != nil { 129 log.Fatalln("Failed to create directory to locate or save dev certificates:", err) 130 } 131 132 certOut, err := os.Create(filepath.Join(devcertsPath, "cert.pem")) 133 if err != nil { 134 log.Fatalln("Failed to open devcerts/cert.pem for writing:", err) 135 } 136 pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) 137 certOut.Close() 138 139 keyOut, err := os.OpenFile(filepath.Join(devcertsPath, "key.pem"), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) 140 if err != nil { 141 log.Fatalln("Failed to open devcerts/key.pem for writing:", err) 142 return 143 } 144 pem.Encode(keyOut, pemBlockForKey(priv)) 145 keyOut.Close() 146 }