Add support for Chrome/Chromium on Linux

Fixes #11
Closes #15
This commit is contained in:
Filippo Valsorda 2018-07-03 22:26:37 -04:00
parent 02f776146c
commit ce54575308
5 changed files with 56 additions and 33 deletions

@ -37,7 +37,15 @@ brew install --HEAD https://github.com/FiloSottile/mkcert/raw/master/HomebrewFor
brew install nss # if you use Firefox
```
On Linux (`-install` support coming soon!), use [the pre-built binaries (again, coming soon)](https://github.com/FiloSottile/mkcert/releases), or build from source (requires Go 1.10+).
On Linux, install `certutil`
```
sudo apt install libnss3-tools
-or-
sudo yum install nss-tools
```
and build from source (requires Go 1.10+), or use [the pre-built binaries (coming soon)](https://github.com/FiloSottile/mkcert/releases).
```
go get -u github.com/FiloSottile/mkcert

21
main.go

@ -79,9 +79,9 @@ func (m *mkcert) Run(args []string) {
warning = true
log.Println("Warning: the local CA is not installed in the system trust store! ⚠️")
}
if hasFirefox && !m.checkFirefox() {
if hasNSS && !m.checkNSS() {
warning = true
log.Println("Warning: the local CA is not installed in the Firefox trust store! ⚠️")
log.Printf("Warning: the local CA is not installed in the %s trust store! ⚠️", NSSBrowsers)
}
if warning {
log.Println("Run \"mkcert -install\" to avoid verification errors ‼️")
@ -163,21 +163,20 @@ func (m *mkcert) install() {
var printed bool
if !m.checkPlatform() {
m.installPlatform()
m.ignoreCheckFailure = true // TODO: replace with a check for a successful install
// TODO: replace with a check for a successful install, drop OS check
m.ignoreCheckFailure = true
if runtime.GOOS != "linux" {
log.Print("The local CA is now installed in the system trust store! ⚡️")
}
printed = true
}
if hasFirefox && !m.checkFirefox() {
if hasNSS && !m.checkNSS() {
if hasCertutil {
m.installFirefox()
log.Print("The local CA is now installed in the Firefox trust store (requires restart)! 🦊")
m.installNSS()
log.Printf("The local CA is now installed in the %s trust store (requires browser restart)! 🦊", NSSBrowsers)
} else {
log.Println(`Warning: "certutil" is not available, so the CA can't be automatically installed in Firefox! ⚠️`)
log.Printf(`Warning: "certutil" is not available, so the CA can't be automatically installed in %s! ⚠️`, NSSBrowsers)
log.Printf(`Install "certutil" with "%s" and re-run "mkcert -install" 👈`, CertutilInstallHelp)
}
printed = true
@ -189,12 +188,12 @@ func (m *mkcert) install() {
func (m *mkcert) uninstall() {
m.uninstallPlatform()
if hasFirefox {
if hasNSS {
if hasCertutil {
m.uninstallFirefox()
m.uninstallNSS()
} 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(`Warning: "certutil" is not available, so the CA can't be automatically uninstalled from %s (if it was ever installed)! ⚠️`, NSSBrowsers)
log.Printf(`You can install "certutil" with "%s" and re-run "mkcert -uninstall" 👈`, CertutilInstallHelp)
log.Print("")
}

@ -20,6 +20,7 @@ var (
FirefoxPath = "/Applications/Firefox.app"
FirefoxProfile = os.Getenv("HOME") + "/Library/Application Support/Firefox/Profiles/*"
CertutilInstallHelp = "brew install nss"
NSSBrowsers = "Firefox"
)
// https://github.com/golang/go/issues/24652#issuecomment-399826583

@ -13,7 +13,8 @@ import (
var (
FirefoxPath = "/usr/bin/firefox"
FirefoxProfile = os.Getenv("HOME") + "/.mozilla/firefox/*"
CertutilInstallHelp = "apt install libnss3-tools"
CertutilInstallHelp = `apt install libnss3-tools" or "yum install nss-tools`
NSSBrowsers = "Firefox and/or Chrome/Chromium"
)
func (m *mkcert) installPlatform() {

@ -10,31 +10,42 @@ import (
)
var (
hasFirefox bool
hasNSS bool
hasCertutil bool
certutilPath string
nssDB = filepath.Join(os.Getenv("HOME"), ".pki/nssdb")
)
func init() {
_, err := os.Stat(FirefoxPath)
hasFirefox = !os.IsNotExist(err)
hasNSS = !os.IsNotExist(err)
out, err := exec.Command("brew", "--prefix", "nss").Output()
if err != nil {
return
switch runtime.GOOS {
case "darwin":
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)
case "linux":
_, err := os.Stat(nssDB)
hasNSS = hasNSS && !os.IsNotExist(err)
certutilPath, err = exec.LookPath("certutil")
hasCertutil = err == nil
}
certutilPath = filepath.Join(strings.TrimSpace(string(out)), "bin", "certutil")
_, err = os.Stat(certutilPath)
hasCertutil = !os.IsNotExist(err)
}
func (m *mkcert) checkFirefox() bool {
func (m *mkcert) checkNSS() bool {
if !hasCertutil {
return false
}
success := true
if m.forEachFirefoxProfile(func(profile string) {
if m.forEachNSSProfile(func(profile string) {
err := exec.Command(certutilPath, "-V", "-d", profile, "-u", "L", "-n", m.caUniqueName()).Run()
if err != nil {
success = false
@ -45,8 +56,8 @@ func (m *mkcert) checkFirefox() bool {
return success
}
func (m *mkcert) installFirefox() {
if m.forEachFirefoxProfile(func(profile string) {
func (m *mkcert) installNSS() {
if m.forEachNSSProfile(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()
if err != nil {
@ -57,16 +68,16 @@ func (m *mkcert) installFirefox() {
}
fatalIfCmdErr(err, "certutil -A", out)
}) == 0 {
log.Println("ERROR: no Firefox security databases found")
log.Printf("ERROR: no %s security databases found", NSSBrowsers)
}
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.")
if !m.checkNSS() {
log.Printf("Installing in %s failed. Please report the issue with details about your environment at https://github.com/FiloSottile/mkcert/issues/new 👎", NSSBrowsers)
log.Printf("Note that if you never started %s, you need to do that at least once.", NSSBrowsers)
}
}
func (m *mkcert) uninstallFirefox() {
m.forEachFirefoxProfile(func(profile string) {
func (m *mkcert) uninstallNSS() {
m.forEachNSSProfile(func(profile string) {
err := exec.Command(certutilPath, "-V", "-d", profile, "-u", "L", "-n", m.caUniqueName()).Run()
if err != nil {
return
@ -77,8 +88,11 @@ func (m *mkcert) uninstallFirefox() {
})
}
func (m *mkcert) forEachFirefoxProfile(f func(profile string)) (found int) {
func (m *mkcert) forEachNSSProfile(f func(profile string)) (found int) {
profiles, _ := filepath.Glob(FirefoxProfile)
if _, err := os.Stat(nssDB); !os.IsNotExist(err) {
profiles = append(profiles, nssDB)
}
if len(profiles) == 0 {
return
}