parent
7544098b30
commit
e4c5c312a7
@ -33,16 +33,17 @@ On macOS, use Homebrew.
|
||||
|
||||
```
|
||||
brew install --HEAD https://github.com/FiloSottile/mkcert/raw/master/HomebrewFormula/mkcert.rb
|
||||
brew install nss # if you use Firefox
|
||||
```
|
||||
|
||||
On Linux (install support coming soon!), use [the pre-built binaries](https://github.com/FiloSottile/mkcert/releases), or build from source.
|
||||
On Linux (`-install` support coming soon!), use [the pre-built binaries (again, coming soon)](https://github.com/FiloSottile/mkcert/releases), or build from source.
|
||||
|
||||
```
|
||||
$ git clone https://github.com/FiloSottile/mkcert
|
||||
$ cd mkcert && make
|
||||
```
|
||||
|
||||
Windows will be supported soon.
|
||||
Windows will be supported next.
|
||||
|
||||
## Advanced topics
|
||||
|
||||
|
4
cert.go
4
cert.go
@ -150,3 +150,7 @@ func (m *mkcert) newCA() {
|
||||
|
||||
log.Printf("Created a new local CA at \"%s\" 💥\n", m.CAROOT)
|
||||
}
|
||||
|
||||
func (m *mkcert) caUniqueName() string {
|
||||
return "mkcert development CA " + m.caCert.SerialNumber.String()
|
||||
}
|
||||
|
65
main.go
65
main.go
@ -62,9 +62,19 @@ func (m *mkcert) Run(args []string) {
|
||||
} else if m.uninstallMode {
|
||||
m.uninstall()
|
||||
return
|
||||
} else if !m.check() {
|
||||
log.Println("Warning: the local CA is not installed in the system trust store! ⚠️")
|
||||
log.Println("Run \"mkcert -install\" to avoid verification errors ‼️")
|
||||
} else {
|
||||
var warning bool
|
||||
if !m.checkPlatform() {
|
||||
warning = true
|
||||
log.Println("Warning: the local CA is not installed in the system trust store! ⚠️")
|
||||
}
|
||||
if hasFirefox && !m.checkFirefox() {
|
||||
warning = true
|
||||
log.Println("Warning: the local CA is not installed in the Firefox trust store! ⚠️")
|
||||
}
|
||||
if warning {
|
||||
log.Println("Run \"mkcert -install\" to avoid verification errors ‼️")
|
||||
}
|
||||
}
|
||||
|
||||
if len(args) == 0 {
|
||||
@ -134,26 +144,45 @@ func getCAROOT() string {
|
||||
}
|
||||
|
||||
func (m *mkcert) install() {
|
||||
if m.check() {
|
||||
return
|
||||
var printed bool
|
||||
if !m.checkPlatform() {
|
||||
m.installPlatform()
|
||||
m.ignoreCheckFailure = true // TODO: replace with a check for a successful install
|
||||
log.Print("The local CA is now installed in the system trust store! ⚡️")
|
||||
printed = true
|
||||
}
|
||||
|
||||
m.installPlatform()
|
||||
m.ignoreCheckFailure = true
|
||||
|
||||
if m.check() { // useless, see comment on ignoreCheckFailure
|
||||
log.Print("The local CA is now installed in the system trust store! ⚡️\n\n")
|
||||
} else {
|
||||
log.Fatal("Installing failed. Please report the issue with details about your environment at https://github.com/FiloSottile/mkcert/issues/new 👎\n\n")
|
||||
if hasFirefox && !m.checkFirefox() {
|
||||
if hasCertutil {
|
||||
m.installFirefox()
|
||||
log.Print("The local CA is now installed in the Firefox trust store (requires restart)! 🦊")
|
||||
} else {
|
||||
log.Println(`Warning: "certutil" is not available, so the CA can't be automatically installed in Firefox! ⚠️`)
|
||||
log.Printf(`Install "certutil" with "%s" and re-run "mkcert -install" 👈`, CertutilInstallHelp)
|
||||
}
|
||||
printed = true
|
||||
}
|
||||
if printed {
|
||||
log.Print("")
|
||||
}
|
||||
}
|
||||
|
||||
func (m *mkcert) uninstall() {
|
||||
m.uninstallPlatform()
|
||||
log.Print("The local CA is now uninstalled from the system trust store! 👋\n\n")
|
||||
if hasFirefox {
|
||||
if hasCertutil {
|
||||
m.uninstallFirefox()
|
||||
} else {
|
||||
log.Print("")
|
||||
log.Println(`Warning: "certutil" is not available, so the CA can't be automatically uninstalled from Firefox (if it was ever installed)! ⚠️`)
|
||||
log.Printf(`You can install "certutil" with "%s" and re-run "mkcert -uninstall" 👈`, CertutilInstallHelp)
|
||||
log.Print("")
|
||||
}
|
||||
}
|
||||
log.Print("The local CA is now uninstalled from the system trust store(s)! 👋")
|
||||
log.Print("")
|
||||
}
|
||||
|
||||
func (m *mkcert) check() bool {
|
||||
func (m *mkcert) checkPlatform() bool {
|
||||
if m.ignoreCheckFailure {
|
||||
return true
|
||||
}
|
||||
@ -167,3 +196,9 @@ func fatalIfErr(err error, msg string) {
|
||||
log.Fatalf("ERROR: %s: %s", msg, err)
|
||||
}
|
||||
}
|
||||
|
||||
func fatalIfCmdErr(err error, cmd string, out []byte) {
|
||||
if err != nil {
|
||||
log.Fatalf("ERROR: failed to execute \"%s\": %s\n\n%s\n", cmd, err, out)
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,12 @@ import (
|
||||
"github.com/DHowett/go-plist"
|
||||
)
|
||||
|
||||
var (
|
||||
FirefoxPath = "/Applications/Firefox.app"
|
||||
FirefoxProfile = os.Getenv("HOME") + "/Library/Application Support/Firefox/Profiles/*"
|
||||
CertutilInstallHelp = "brew install nss"
|
||||
)
|
||||
|
||||
// https://github.com/golang/go/issues/24652#issuecomment-399826583
|
||||
var trustSettings []interface{}
|
||||
var _, _ = plist.Unmarshal(trustSettingsData, &trustSettings)
|
||||
@ -100,9 +106,3 @@ func (m *mkcert) uninstallPlatform() {
|
||||
out, err := cmd.CombinedOutput()
|
||||
fatalIfCmdErr(err, "security remove-trusted-cert", out)
|
||||
}
|
||||
|
||||
func fatalIfCmdErr(err error, cmd string, out []byte) {
|
||||
if err != nil {
|
||||
log.Fatalf("ERROR: failed to execute \"%s\": %s\n\n%s\n", cmd, err, out)
|
||||
}
|
||||
}
|
||||
|
89
truststore_firefox.go
Normal file
89
truststore_firefox.go
Normal file
@ -0,0 +1,89 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
hasFirefox bool
|
||||
hasCertutil bool
|
||||
certutilPath string
|
||||
)
|
||||
|
||||
func init() {
|
||||
_, err := os.Stat(FirefoxPath)
|
||||
hasFirefox = !os.IsNotExist(err)
|
||||
|
||||
out, err := exec.Command("brew", "--prefix", "nss").Output()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
certutilPath = filepath.Join(strings.TrimSpace(string(out)), "bin", "certutil")
|
||||
|
||||
_, err = os.Stat(certutilPath)
|
||||
hasCertutil = !os.IsNotExist(err)
|
||||
}
|
||||
|
||||
func (m *mkcert) checkFirefox() bool {
|
||||
if !hasCertutil {
|
||||
return false
|
||||
}
|
||||
success := true
|
||||
if m.forEachFirefoxProfile(func(profile string) {
|
||||
err := exec.Command(certutilPath, "-V", "-d", profile, "-u", "L", "-n", m.caUniqueName()).Run()
|
||||
if err != nil {
|
||||
success = false
|
||||
}
|
||||
}) == 0 {
|
||||
success = false
|
||||
}
|
||||
return success
|
||||
}
|
||||
|
||||
func (m *mkcert) installFirefox() {
|
||||
if m.forEachFirefoxProfile(func(profile string) {
|
||||
cmd := exec.Command(certutilPath, "-A", "-d", profile, "-t", "C,,", "-n", m.caUniqueName(), "-i", filepath.Join(m.CAROOT, rootName))
|
||||
out, err := cmd.CombinedOutput()
|
||||
fatalIfCmdErr(err, "certutil -A", out)
|
||||
}) == 0 {
|
||||
log.Println("ERROR: no Firefox security databases found")
|
||||
}
|
||||
if !m.checkFirefox() {
|
||||
log.Println("Installing in Firefox failed. Please report the issue with details about your environment at https://github.com/FiloSottile/mkcert/issues/new 👎")
|
||||
log.Println("Note that if you never started Firefox, you need to do that at least once.")
|
||||
}
|
||||
}
|
||||
|
||||
func (m *mkcert) uninstallFirefox() {
|
||||
m.forEachFirefoxProfile(func(profile string) {
|
||||
err := exec.Command(certutilPath, "-V", "-d", profile, "-u", "L", "-n", m.caUniqueName()).Run()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
cmd := exec.Command(certutilPath, "-D", "-d", profile, "-n", m.caUniqueName())
|
||||
out, err := cmd.CombinedOutput()
|
||||
fatalIfCmdErr(err, "certutil -D", out)
|
||||
})
|
||||
}
|
||||
|
||||
func (m *mkcert) forEachFirefoxProfile(f func(profile string)) (found int) {
|
||||
profiles, _ := filepath.Glob(FirefoxProfile)
|
||||
if len(profiles) == 0 {
|
||||
return
|
||||
}
|
||||
for _, profile := range profiles {
|
||||
if _, err := os.Stat(filepath.Join(profile, "cert8.db")); !os.IsNotExist(err) {
|
||||
f(profile)
|
||||
found++
|
||||
}
|
||||
if _, err := os.Stat(filepath.Join(profile, "cert9.db")); !os.IsNotExist(err) {
|
||||
f("sql:" + profile)
|
||||
found++
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
@ -6,9 +6,16 @@ package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
var (
|
||||
FirefoxPath = "/usr/bin/firefox"
|
||||
FirefoxProfile = os.Getenv("HOME") + "/.mozilla/firefox/*"
|
||||
CertutilInstallHelp = "apt install libnss3-tools"
|
||||
)
|
||||
|
||||
func (m *mkcert) installPlatform() {
|
||||
log.Fatalf("-install is not yet supported on Linux 😣\nYou can manually install the root certificate at %q in the meantime.", filepath.Join(m.CAROOT, rootName))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user