-
Notifications
You must be signed in to change notification settings - Fork 0
/
mkcert.go
140 lines (101 loc) · 2.74 KB
/
mkcert.go
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package server
// https://github.com/FiloSottile/mkcert/issues/45
import (
"context"
"errors"
"fmt"
"log"
"net/url"
"os"
"os/exec"
"path/filepath"
"strings"
)
const MKCERT string = "mkcert"
func init() {
ctx := context.Background()
RegisterServer(ctx, "mkcert", NewMkCertServer)
}
// NewMkCertServer returns a new `HTTPServer` instance configured using 'uri'
// in the form of:
//
// mkcert://?{PARAMETERS}
//
// Valid parameters are:
// - `root={PATH}` An optional path to specify where `mkcert` certificates and keys should be created. If missing
// the operating system's temporary directory will be used.
func NewMkCertServer(ctx context.Context, uri string) (Server, error) {
u, err := url.Parse(uri)
if err != nil {
return nil, err
}
q := u.Query()
root := q.Get("root")
if root == "" {
root = os.TempDir()
} else {
abs_root, err := filepath.Abs(root)
if err != nil {
return nil, err
}
info, err := os.Stat(abs_root)
if err != nil {
return nil, err
}
if !info.IsDir() {
return nil, errors.New("Invalid root")
}
root = abs_root
}
server_uri := fmt.Sprintf("https://%s", u.Host)
server_u, err := url.Parse(server_uri)
if err != nil {
return nil, err
}
tls_cert, tls_key, err := mkCert(server_u, root)
if err != nil {
return nil, err
}
server_params := url.Values{}
server_params.Set("cert", tls_cert)
server_params.Set("key", tls_key)
server_u.RawQuery = server_params.Encode()
https_uri := server_u.String()
return NewServer(ctx, https_uri)
}
// mkCert creates a new TLS certificate and key using the `mkcert` binary stored in 'root'.
func mkCert(u *url.URL, root string) (string, string, error) {
err := mkCertInstall()
if err != nil {
return "", "", err
}
parts := strings.Split(u.Host, ":")
host := parts[0]
cert_fname := fmt.Sprintf("%s-cert.pem", host)
key_fname := fmt.Sprintf("%s-key.pem", host)
cert_path := filepath.Join(root, cert_fname)
key_path := filepath.Join(root, key_fname)
args := []string{
"-cert-file",
cert_path,
"-key-file",
key_path,
host,
}
cmd := exec.Command(MKCERT, args...)
err = cmd.Run()
if err != nil {
return "", "", err
}
return cert_path, key_path, nil
}
// mkCertInstall ensures that the `mkcert` binary is present and can be executed.
func mkCertInstall() error {
// unfortunately there is no way from the CLI tool to check whether
// mkcert is installed and some of the built-in methods for testing
// state (in mkcert.go) are marked as private so there's no way to
// access them... (20200420/thisisaaronland)
log.Println("Checking whether mkcert is installed. If it is not you may be prompted for your password (in order to install certificate files")
cmd := exec.Command(MKCERT, "-install")
return cmd.Run()
}