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 --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
|
$ git clone https://github.com/FiloSottile/mkcert
|
||||||
$ cd mkcert && make
|
$ cd mkcert && make
|
||||||
```
|
```
|
||||||
|
|
||||||
Windows will be supported soon.
|
Windows will be supported next.
|
||||||
|
|
||||||
## Advanced topics
|
## 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)
|
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()
|
||||||
|
}
|
||||||
|
59
main.go
59
main.go
@ -62,10 +62,20 @@ func (m *mkcert) Run(args []string) {
|
|||||||
} else if m.uninstallMode {
|
} else if m.uninstallMode {
|
||||||
m.uninstall()
|
m.uninstall()
|
||||||
return
|
return
|
||||||
} else if !m.check() {
|
} else {
|
||||||
|
var warning bool
|
||||||
|
if !m.checkPlatform() {
|
||||||
|
warning = true
|
||||||
log.Println("Warning: the local CA is not installed in the system trust store! ⚠️")
|
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 ‼️")
|
log.Println("Run \"mkcert -install\" to avoid verification errors ‼️")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
log.Printf(`
|
log.Printf(`
|
||||||
@ -134,26 +144,45 @@ func getCAROOT() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *mkcert) install() {
|
func (m *mkcert) install() {
|
||||||
if m.check() {
|
var printed bool
|
||||||
return
|
if !m.checkPlatform() {
|
||||||
}
|
|
||||||
|
|
||||||
m.installPlatform()
|
m.installPlatform()
|
||||||
m.ignoreCheckFailure = true
|
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! ⚡️")
|
||||||
if m.check() { // useless, see comment on ignoreCheckFailure
|
printed = true
|
||||||
log.Print("The local CA is now installed in the system trust store! ⚡️\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 {
|
} else {
|
||||||
log.Fatal("Installing failed. Please report the issue with details about your environment at https://github.com/FiloSottile/mkcert/issues/new 👎\n\n")
|
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() {
|
func (m *mkcert) uninstall() {
|
||||||
m.uninstallPlatform()
|
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 {
|
if m.ignoreCheckFailure {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -167,3 +196,9 @@ func fatalIfErr(err error, msg string) {
|
|||||||
log.Fatalf("ERROR: %s: %s", msg, err)
|
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"
|
"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
|
// https://github.com/golang/go/issues/24652#issuecomment-399826583
|
||||||
var trustSettings []interface{}
|
var trustSettings []interface{}
|
||||||
var _, _ = plist.Unmarshal(trustSettingsData, &trustSettings)
|
var _, _ = plist.Unmarshal(trustSettingsData, &trustSettings)
|
||||||
@ -100,9 +106,3 @@ func (m *mkcert) uninstallPlatform() {
|
|||||||
out, err := cmd.CombinedOutput()
|
out, err := cmd.CombinedOutput()
|
||||||
fatalIfCmdErr(err, "security remove-trusted-cert", out)
|
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 (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
FirefoxPath = "/usr/bin/firefox"
|
||||||
|
FirefoxProfile = os.Getenv("HOME") + "/.mozilla/firefox/*"
|
||||||
|
CertutilInstallHelp = "apt install libnss3-tools"
|
||||||
|
)
|
||||||
|
|
||||||
func (m *mkcert) installPlatform() {
|
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))
|
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