Skip to content

Commit ce87078

Browse files
Prompt Safari users to install HTTPS certificates and check if they are outdated when the Agent is started
1 parent 5699410 commit ce87078

File tree

2 files changed

+78
-0
lines changed

2 files changed

+78
-0
lines changed

certificates/certificates.go

+35
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"math/big"
3131
"net"
3232
"os"
33+
"os/exec"
3334
"strings"
3435
"time"
3536

@@ -279,3 +280,37 @@ func IsExpired() (bool, error) {
279280
date, _ := time.Parse(time.DateTime, strings.ReplaceAll(dateS, " +0000", ""))
280281
return date.Before(bound), nil
281282
}
283+
284+
// PromptInstallCertsSafari prompts the user to install the HTTPS certificates if they are using Safari
285+
func PromptInstallCertsSafari() bool {
286+
if GetDefaultBrowserName() != "Safari" {
287+
return false
288+
}
289+
oscmd := exec.Command("osascript", "-e", "display dialog \"The Arduino Agent needs a local HTTPS certificate to work correctly with Safari.\nIf you use Safari, you need to install it.\" buttons {\"Do not install\", \"Install the certificate for Safari\"} default button 1 with title \"Install Certificates\"")
290+
pressed, _ := oscmd.Output()
291+
return string(pressed) == "button returned:Install the certificate for Safari"
292+
}
293+
294+
// PromptExpiredCerts prompts the user to update the HTTPS certificates if they are using Safari
295+
func PromptExpiredCerts(certDir *paths.Path) {
296+
if expired, err := IsExpired(); err != nil {
297+
log.Errorf("cannot check if certificates are expired something went wrong: %s", err)
298+
} else if expired {
299+
oscmd := exec.Command("osascript", "-e", "display dialog \"The Arduino Agent needs a local HTTPS certificate to work correctly with Safari.\nYour certificate is expired or close to expiration. Do you want to update it?\" buttons {\"Do not update\", \"Update the certificate for Safari\"} default button 1 with title \"Update Certificates\"")
300+
if pressed, _ := oscmd.Output(); string(pressed) == "button returned:Update the certificate for Safari" {
301+
err := UninstallCertificates()
302+
if err != nil {
303+
log.Errorf("cannot uninstall certificates something went wrong: %s", err)
304+
} else {
305+
DeleteCertificates(certDir)
306+
GenerateCertificates(certDir)
307+
err := InstallCertificate(certDir.Join("ca.cert.cer"))
308+
// if something goes wrong during the cert install we remove them, so the user is able to retry
309+
if err != nil {
310+
log.Errorf("cannot install certificates something went wrong: %s", err)
311+
DeleteCertificates(certDir)
312+
}
313+
}
314+
}
315+
}
316+
}

main.go

+43
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ var (
8686
verbose = iniConf.Bool("v", true, "show debug logging")
8787
crashreport = iniConf.Bool("crashreport", false, "enable crashreport logging")
8888
autostartMacOS = iniConf.Bool("autostartMacOS", true, "the Arduino Create Agent is able to start automatically after login on macOS (launchd agent)")
89+
installCerts = iniConf.Bool("installCerts", false, "")
8990
)
9091

9192
// the ports filter provided by the user via the -regex flag, if any
@@ -220,6 +221,17 @@ func loop() {
220221
configPath = config.GenerateConfig(configDir)
221222
}
222223

224+
if runtime.GOOS == "darwin" {
225+
if value, err := valueIni(configPath.String()); err != nil {
226+
log.Panicf("config.ini cannot be parsed: %s", err)
227+
} else if !value && cert.PromptInstallCertsSafari() {
228+
err = modifyIni(configPath.String())
229+
if err != nil {
230+
log.Panicf("config.ini cannot be parsed: %s", err)
231+
}
232+
}
233+
}
234+
223235
// Parse the config.ini
224236
args, err := parseIni(configPath.String())
225237
if err != nil {
@@ -342,6 +354,13 @@ func loop() {
342354
}
343355
}
344356

357+
// check if the certificates are expired and prompt the user to update them on macOS
358+
if runtime.GOOS == "darwin" {
359+
if *installCerts {
360+
cert.PromptExpiredCerts(config.GetCertificatesDir())
361+
}
362+
}
363+
345364
// launch the discoveries for the running system
346365
go serialPorts.Run()
347366
// launch the hub routine which is the singleton for the websocket server
@@ -487,3 +506,27 @@ func parseIni(filename string) (args []string, err error) {
487506

488507
return args, nil
489508
}
509+
510+
func modifyIni(filename string) error {
511+
cfg, err := ini.LoadSources(ini.LoadOptions{IgnoreInlineComment: false, AllowPythonMultilineValues: true}, filename)
512+
if err != nil {
513+
return err
514+
}
515+
_, err = cfg.Section("").NewKey("installCerts", "true")
516+
if err != nil {
517+
return err
518+
}
519+
err = cfg.SaveTo(filename)
520+
if err != nil {
521+
return err
522+
}
523+
return nil
524+
}
525+
526+
func valueIni(filename string) (bool, error) {
527+
cfg, err := ini.LoadSources(ini.LoadOptions{IgnoreInlineComment: false, AllowPythonMultilineValues: true}, filename)
528+
if err != nil {
529+
return false, err
530+
}
531+
return cfg.Section("").HasKey("installCerts"), nil
532+
}

0 commit comments

Comments
 (0)