summaryrefslogtreecommitdiff
path: root/system/tls/enable.go
blob: 77ff28751b4b55cd5f4b2c8d48e60edf89755170 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package tls

import (
	"crypto/tls"
	"fmt"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"time"

	"github.com/ponzu-cms/ponzu/system/db"

	"golang.org/x/crypto/acme/autocert"
)

var m autocert.Manager

// setup attempts to locate or create the cert cache directory and the certs for TLS encryption
func setup() {
	pwd, err := os.Getwd()
	if err != nil {
		log.Fatalln("Couldn't find working directory to locate or save certificates.")
	}

	cache := autocert.DirCache(filepath.Join(pwd, "system", "tls", "certs"))
	if _, err := os.Stat(string(cache)); os.IsNotExist(err) {
		err := os.MkdirAll(string(cache), os.ModePerm|os.ModeDir)
		if err != nil {
			log.Fatalln("Couldn't create cert directory at", cache)
		}
	}

	// get host/domain and email from Config to use for TLS request to Let's encryption.
	// we will fail fatally if either are not found since Let's Encrypt will rate-limit
	// and sending incomplete requests is wasteful and guarenteed to fail its check
	host, err := db.Config("domain")
	if err != nil {
		log.Fatalln("Error identifying host/domain during TLS set-up.", err)
	}

	if host == nil {
		log.Fatalln("No 'domain' field set in Configuration. Please add a domain before attempting to make certificates.")
	}
	fmt.Println("Using", string(host), "as host/domain for certificate...")
	fmt.Println("NOTE: if the host/domain is not configured properly or is unreachable, HTTPS set-up will fail.")

	email, err := db.Config("admin_email")
	if err != nil {
		log.Fatalln("Error identifying admin email during TLS set-up.", err)
	}

	if email == nil {
		log.Fatalln("No 'admin_email' field set in Configuration. Please add an admin email before attempting to make certificates.")
	}
	fmt.Println("Using", string(email), "as contact email for certificate...")

	m = autocert.Manager{
		Prompt:      autocert.AcceptTOS,
		Cache:       cache,
		HostPolicy:  autocert.HostWhitelist(string(host)),
		RenewBefore: time.Hour * 24 * 30,
		Email:       string(email),
	}

}

// Enable runs the setup for creating or locating production certificates and
// starts the TLS server
func Enable() {
	setup()

	server := &http.Server{
		Addr:      ":443",
		TLSConfig: &tls.Config{GetCertificate: m.GetCertificate},
	}

	go log.Fatalln(server.ListenAndServeTLS("", ""))
	fmt.Println("Server listening on :443 for HTTPS requests...")
}