summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Manuel <nilslice@gmail.com>2016-12-27 10:53:40 -0800
committerSteve Manuel <nilslice@gmail.com>2016-12-27 10:53:40 -0800
commitbe0180623c456ea661c3d71fb13dbeb1f1ba7bd1 (patch)
tree2854bcc9e84833085b977828e537853c07b932f6
parent3055df5e17b6c58566eecb1e0a44cf6efc01a530 (diff)
adding self-signed cert generator for local https/http2 testing
-rw-r--r--cmd/ponzu/main.go22
-rw-r--r--system/tls/devcerts.go143
-rw-r--r--system/tls/enable.go3
-rw-r--r--system/tls/enabledev.go23
4 files changed, 183 insertions, 8 deletions
diff --git a/cmd/ponzu/main.go b/cmd/ponzu/main.go
index 9900d40..3764984 100644
--- a/cmd/ponzu/main.go
+++ b/cmd/ponzu/main.go
@@ -20,9 +20,10 @@ import (
)
var (
- usage = usageHeader + usageNew + usageGenerate + usageBuild + usageRun
- port int
- https bool
+ usage = usageHeader + usageNew + usageGenerate + usageBuild + usageRun
+ port int
+ https bool
+ devhttps bool
// for ponzu internal / core development
dev bool
@@ -30,15 +31,14 @@ var (
gocmd string
)
-func init() {
+func main() {
flag.Usage = func() {
fmt.Println(usage)
}
-}
-func main() {
flag.IntVar(&port, "port", 8080, "port for ponzu to bind its listener")
flag.BoolVar(&https, "https", false, "enable automatic TLS/SSL certificate management")
+ flag.BoolVar(&devhttps, "devhttps", false, "[dev environment] enable automatic TLS/SSL certificate management")
flag.BoolVar(&dev, "dev", false, "modify environment for Ponzu core development")
flag.StringVar(&fork, "fork", "", "modify repo source for Ponzu core development")
flag.StringVar(&gocmd, "gocmd", "go", "custom go command if using beta or new release of Go")
@@ -116,6 +116,10 @@ func main() {
addTLS = "--https=false"
}
+ if devhttps {
+ addTLS = "--devhttps"
+ }
+
var services string
if len(args) > 1 {
services = args[1]
@@ -167,7 +171,11 @@ func main() {
}
}
- if https {
+ // cannot run production HTTPS and development HTTPS together
+ if devhttps {
+ fmt.Println("Enabling self-signed HTTPS...")
+ tls.EnableDev()
+ } else if https {
fmt.Println("Enabling HTTPS...")
tls.Enable()
}
diff --git a/system/tls/devcerts.go b/system/tls/devcerts.go
new file mode 100644
index 0000000..7d07a4a
--- /dev/null
+++ b/system/tls/devcerts.go
@@ -0,0 +1,143 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Modified 2016 by Steve Manuel, Boss Sauce Creative, LLC
+// All modifications are relicensed under the same BSD license
+// found in the LICENSE file.
+
+// Generate a self-signed X.509 certificate for a TLS server. Outputs to
+// 'devcerts/cert.pem' and 'devcerts/key.pem' and will overwrite existing files.
+
+package tls
+
+import (
+ "crypto/ecdsa"
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/x509"
+ "crypto/x509/pkix"
+ "encoding/pem"
+ "fmt"
+ "log"
+ "math/big"
+ "net"
+ "os"
+ "path/filepath"
+ "strings"
+ "time"
+
+ "github.com/ponzu-cms/ponzu/system/db"
+)
+
+func publicKey(priv interface{}) interface{} {
+ switch k := priv.(type) {
+ case *rsa.PrivateKey:
+ return &k.PublicKey
+ case *ecdsa.PrivateKey:
+ return &k.PublicKey
+ default:
+ return nil
+ }
+}
+
+func pemBlockForKey(priv interface{}) *pem.Block {
+ switch k := priv.(type) {
+ case *rsa.PrivateKey:
+ return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(k)}
+ case *ecdsa.PrivateKey:
+ b, err := x509.MarshalECPrivateKey(k)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Unable to marshal ECDSA private key: %v", err)
+ os.Exit(2)
+ }
+ return &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}
+ default:
+ return nil
+ }
+}
+
+func setupDev() {
+ var priv interface{}
+ var err error
+
+ priv, err = rsa.GenerateKey(rand.Reader, 2048)
+
+ if err != nil {
+ log.Fatalf("failed to generate private key: %s", err)
+ }
+
+ notBefore := time.Now()
+ notAfter := notBefore.Add(time.Hour * 24 * 30) // valid for 30 days
+
+ serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
+ serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
+ if err != nil {
+ log.Fatalf("failed to generate serial number: %s", err)
+ }
+
+ template := x509.Certificate{
+ SerialNumber: serialNumber,
+ Subject: pkix.Name{
+ Organization: []string{"Acme Co"},
+ },
+ NotBefore: notBefore,
+ NotAfter: notAfter,
+
+ KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
+ ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
+ BasicConstraintsValid: true,
+ }
+
+ host := db.ConfigCache("domain")
+ if host == "" {
+ host = "localhost, 0.0.0.0"
+ }
+ hosts := strings.Split(host, ",")
+ for _, h := range hosts {
+ if ip := net.ParseIP(h); ip != nil {
+ template.IPAddresses = append(template.IPAddresses, ip)
+ } else {
+ template.DNSNames = append(template.DNSNames, h)
+ }
+ }
+
+ // make all certs CA
+ template.IsCA = true
+ template.KeyUsage |= x509.KeyUsageCertSign
+
+ derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv)
+ if err != nil {
+ log.Fatalln("Failed to create certificate:", err)
+ }
+
+ // overwrite/create directory for devcerts
+ pwd, err := os.Getwd()
+ if err != nil {
+ log.Fatalln("Couldn't find working directory to locate or save dev certificates.")
+ }
+
+ devcertsPath := filepath.Join(pwd, "system", "tls", "devcerts")
+
+ err = os.Mkdir(devcertsPath, os.ModePerm|os.ModePerm)
+ if err != nil {
+ log.Fatalln("Failed to create directory to locate or save dev certificates.")
+ }
+
+ certOut, err := os.Create(filepath.Join(devcertsPath, "cert.pem"))
+ if err != nil {
+ log.Fatalf("failed to open devcerts/cert.pem for writing: %s", err)
+ }
+ pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
+ certOut.Close()
+ log.Print("written devcerts/cert.pem\n")
+
+ keyOut, err := os.OpenFile(filepath.Join(devcertsPath, "key.pem"), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
+ if err != nil {
+ log.Print("failed to open devcerts/key.pem for writing:", err)
+ return
+ }
+ pem.Encode(keyOut, pemBlockForKey(priv))
+ keyOut.Close()
+ log.Print("written devcerts/key.pem\n")
+}
diff --git a/system/tls/enable.go b/system/tls/enable.go
index 04f032a..5e16b92 100644
--- a/system/tls/enable.go
+++ b/system/tls/enable.go
@@ -65,7 +65,8 @@ func setup() {
}
-// Enable runs the setup for creating or locating certificates and starts the TLS server
+// Enable runs the setup for creating or locating production certificates and
+// starts the TLS server
func Enable() {
setup()
diff --git a/system/tls/enabledev.go b/system/tls/enabledev.go
new file mode 100644
index 0000000..18da161
--- /dev/null
+++ b/system/tls/enabledev.go
@@ -0,0 +1,23 @@
+package tls
+
+import (
+ "log"
+ "net/http"
+ "path/filepath"
+)
+
+// EnableDev generates self-signed SSL certificates to use HTTPS & HTTP/2 while
+// working in a development environment. The certs are saved in a different
+// directory than the production certs (from Let's Encrypt), so that the
+// acme/autocert package doesn't mistake them for it's own.
+// Additionally, a TLS server is started using the default http mux.
+func EnableDev() {
+ setupDev()
+
+ cert := filepath.Join("devcerts", "cert.pem")
+ key := filepath.Join("devcerts", "key.pem")
+ err := http.ListenAndServeTLS(":10443", cert, key, nil)
+ if err != nil {
+ log.Fatalln(err)
+ }
+}