Browse Source

Add support for Chrome/Chromium on Linux

Fixes #11
Closes #15
Filippo Valsorda 6 years ago
parent
commit
ce54575308
5 changed files with 56 additions and 33 deletions
  1. 9 1
      README.md
  2. 10 11
      main.go
  3. 1 0
      truststore_darwin.go
  4. 2 1
      truststore_linux.go
  5. 34 20
      truststore_nss.go

+ 9 - 1
README.md

@@ -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

+ 10 - 11
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("")
 		}

+ 1 - 0
truststore_darwin.go

@@ -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

+ 2 - 1
truststore_linux.go

@@ -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() {

+ 34 - 20
truststore_firefox.go → truststore_nss.go

@@ -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
-	}
-	certutilPath = filepath.Join(strings.TrimSpace(string(out)), "bin", "certutil")
+	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)
+		_, 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
+	}
 }
 
-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
 	}