diff --git a/internal/app/app.go b/internal/app/app.go index f0c67009..be0ce6fe 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -285,7 +285,7 @@ func run(c *cli.Context) error { skipKeychainTest := checkSkipKeychainTest(c, settings) return WithKeychainList(crashHandler, skipKeychainTest, func(keychains *keychain.List) error { // Unlock the encrypted vault. - return WithVault(locations, keychains, crashHandler, func(v *vault.Vault, insecure, corrupt bool) error { + return WithVault(reporter, locations, keychains, crashHandler, func(v *vault.Vault, insecure, corrupt bool) error { if !v.Migrated() { // Migrate old settings into the vault. if err := migrateOldSettings(v); err != nil { diff --git a/internal/app/vault.go b/internal/app/vault.go index 8ec90f74..9fd3f604 100644 --- a/internal/app/vault.go +++ b/internal/app/vault.go @@ -25,17 +25,18 @@ import ( "github.com/ProtonMail/proton-bridge/v3/internal/certs" "github.com/ProtonMail/proton-bridge/v3/internal/constants" "github.com/ProtonMail/proton-bridge/v3/internal/locations" + "github.com/ProtonMail/proton-bridge/v3/internal/sentry" "github.com/ProtonMail/proton-bridge/v3/internal/vault" "github.com/ProtonMail/proton-bridge/v3/pkg/keychain" "github.com/sirupsen/logrus" ) -func WithVault(locations *locations.Locations, keychains *keychain.List, panicHandler async.PanicHandler, fn func(*vault.Vault, bool, bool) error) error { +func WithVault(reporter *sentry.Reporter, locations *locations.Locations, keychains *keychain.List, panicHandler async.PanicHandler, fn func(*vault.Vault, bool, bool) error) error { logrus.Debug("Creating vault") defer logrus.Debug("Vault stopped") // Create the encVault. - encVault, insecure, corrupt, err := newVault(locations, keychains, panicHandler) + encVault, insecure, corrupt, err := newVault(reporter, locations, keychains, panicHandler) if err != nil { return fmt.Errorf("could not create vault: %w", err) } @@ -57,7 +58,7 @@ func WithVault(locations *locations.Locations, keychains *keychain.List, panicHa return fn(encVault, insecure, corrupt != nil) } -func newVault(locations *locations.Locations, keychains *keychain.List, panicHandler async.PanicHandler) (*vault.Vault, bool, error, error) { +func newVault(reporter *sentry.Reporter, locations *locations.Locations, keychains *keychain.List, panicHandler async.PanicHandler) (*vault.Vault, bool, error, error) { vaultDir, err := locations.ProvideSettingsPath() if err != nil { return nil, false, nil, fmt.Errorf("could not get vault dir: %w", err) @@ -71,6 +72,16 @@ func newVault(locations *locations.Locations, keychains *keychain.List, panicHan ) if key, err := loadVaultKey(vaultDir, keychains); err != nil { + if reporter != nil { + if rerr := reporter.ReportMessageWithContext("Could not load/create vault key", map[string]any{ + "keychainDefaultHelper": keychains.GetDefaultHelper(), + "keychainUsableHelpersLength": len(keychains.GetHelpers()), + "error": err.Error(), + }); rerr != nil { + logrus.WithError(err).Info("Failed to report keychain issue to Sentry") + } + } + logrus.WithError(err).Error("Could not load/create vault key") insecure = true diff --git a/internal/sentry/hostarch_darwin.go b/internal/sentry/hostarch_darwin.go index bb7e5033..23e39b1a 100644 --- a/internal/sentry/hostarch_darwin.go +++ b/internal/sentry/hostarch_darwin.go @@ -21,18 +21,13 @@ package sentry import ( - "github.com/elastic/go-sysinfo" + "github.com/elastic/go-sysinfo/types" "golang.org/x/sys/unix" ) const translatedProcDarwin = "sysctl.proc_translated" -func getHostArch() string { - host, err := sysinfo.Host() - if err != nil { - return "not-detected" - } - +func getHostArch(host types.Host) string { // It is not possible to retrieve real hardware architecture once using // rosetta. But it is possible to detect the process translation if // rosetta is used. diff --git a/internal/sentry/hostarch_default.go b/internal/sentry/hostarch_default.go index 5648e986..4470f8c5 100644 --- a/internal/sentry/hostarch_default.go +++ b/internal/sentry/hostarch_default.go @@ -20,12 +20,10 @@ package sentry -import "github.com/elastic/go-sysinfo" +import ( + "github.com/elastic/go-sysinfo/types" +) -func getHostArch() string { - host, err := sysinfo.Host() - if err != nil { - return "not-detected" - } +func getHostArch(host types.Host) string { return host.Info().Architecture } diff --git a/internal/sentry/reporter.go b/internal/sentry/reporter.go index af5afaaf..929bbf12 100644 --- a/internal/sentry/reporter.go +++ b/internal/sentry/reporter.go @@ -30,10 +30,13 @@ import ( "github.com/ProtonMail/proton-bridge/v3/internal/constants" "github.com/ProtonMail/proton-bridge/v3/pkg/algo" "github.com/ProtonMail/proton-bridge/v3/pkg/restarter" + "github.com/elastic/go-sysinfo" "github.com/getsentry/sentry-go" "github.com/sirupsen/logrus" ) +const hostNotDetectedField = "not-detected" + var skippedFunctions = []string{} //nolint:gochecknoglobals func init() { //nolint:gochecknoinits @@ -70,17 +73,50 @@ func init() { //nolint:gochecknoinits ) } +type hostInfoData struct { + hostArch string + hostName string + hostVersion string + hostBuild string +} + +func newHostInfoData() hostInfoData { + return hostInfoData{ + hostArch: hostNotDetectedField, + hostName: hostNotDetectedField, + hostVersion: hostNotDetectedField, + hostBuild: hostNotDetectedField, + } +} + type Reporter struct { appName string appVersion string identifier Identifier - hostArch string + hostInfo hostInfoData } type Identifier interface { GetUserAgent() string } +func getHostInfo() hostInfoData { + data := newHostInfoData() + + host, err := sysinfo.Host() + if err != nil { + return data + } + + data.hostArch = getHostArch(host) + osInfo := host.Info().OS + data.hostName = osInfo.Name + data.hostVersion = osInfo.Version + data.hostBuild = osInfo.Build + + return data +} + func GetProtectedHostname() string { hostname, err := os.Hostname() if err != nil { @@ -100,7 +136,7 @@ func NewReporter(appName string, identifier Identifier) *Reporter { appName: appName, appVersion: constants.Revision, identifier: identifier, - hostArch: getHostArch(), + hostInfo: getHostInfo(), } } @@ -152,11 +188,14 @@ func (r *Reporter) scopedReport(context map[string]interface{}, doReport func()) } tags := map[string]string{ - "OS": runtime.GOOS, - "Client": r.appName, - "Version": r.appVersion, - "UserAgent": r.identifier.GetUserAgent(), - "HostArch": r.hostArch, + "OS": runtime.GOOS, + "Client": r.appName, + "Version": r.appVersion, + "UserAgent": r.identifier.GetUserAgent(), + "HostArch": r.hostInfo.hostArch, + "HostName": r.hostInfo.hostName, + "HostVersion": r.hostInfo.hostVersion, + "HostBuild": r.hostInfo.hostBuild, } sentry.WithScope(func(scope *sentry.Scope) { diff --git a/utils/bridge-rollout/bridge-rollout.go b/utils/bridge-rollout/bridge-rollout.go index 4df9d0df..becf8b4f 100644 --- a/utils/bridge-rollout/bridge-rollout.go +++ b/utils/bridge-rollout/bridge-rollout.go @@ -62,7 +62,7 @@ func main() { func getRollout(_ *cli.Context) error { return app.WithLocations(func(locations *locations.Locations) error { return app.WithKeychainList(async.NoopPanicHandler{}, false, func(keychains *keychain.List) error { - return app.WithVault(locations, keychains, async.NoopPanicHandler{}, func(vault *vault.Vault, _, _ bool) error { + return app.WithVault(nil, locations, keychains, async.NoopPanicHandler{}, func(vault *vault.Vault, _, _ bool) error { fmt.Println(vault.GetUpdateRollout()) return nil }) @@ -73,7 +73,7 @@ func getRollout(_ *cli.Context) error { func setRollout(c *cli.Context) error { return app.WithLocations(func(locations *locations.Locations) error { return app.WithKeychainList(async.NoopPanicHandler{}, false, func(keychains *keychain.List) error { - return app.WithVault(locations, keychains, async.NoopPanicHandler{}, func(vault *vault.Vault, _, _ bool) error { + return app.WithVault(nil, locations, keychains, async.NoopPanicHandler{}, func(vault *vault.Vault, _, _ bool) error { clamped := max(0.0, min(1.0, c.Float64("value"))) if err := vault.SetUpdateRollout(clamped); err != nil { return err diff --git a/utils/vault-editor/main.go b/utils/vault-editor/main.go index a922e1ea..91d3bfdc 100644 --- a/utils/vault-editor/main.go +++ b/utils/vault-editor/main.go @@ -52,7 +52,7 @@ func main() { func readAction(c *cli.Context) error { return app.WithLocations(func(locations *locations.Locations) error { return app.WithKeychainList(async.NoopPanicHandler{}, false, func(keychains *keychain.List) error { - return app.WithVault(locations, keychains, async.NoopPanicHandler{}, func(vault *vault.Vault, insecure, corrupt bool) error { + return app.WithVault(nil, locations, keychains, async.NoopPanicHandler{}, func(vault *vault.Vault, insecure, corrupt bool) error { if _, err := os.Stdout.Write(vault.ExportJSON()); err != nil { return fmt.Errorf("failed to write vault: %w", err) } @@ -66,7 +66,7 @@ func readAction(c *cli.Context) error { func writeAction(c *cli.Context) error { return app.WithLocations(func(locations *locations.Locations) error { return app.WithKeychainList(async.NoopPanicHandler{}, false, func(keychains *keychain.List) error { - return app.WithVault(locations, keychains, async.NoopPanicHandler{}, func(vault *vault.Vault, insecure, corrupt bool) error { + return app.WithVault(nil, locations, keychains, async.NoopPanicHandler{}, func(vault *vault.Vault, insecure, corrupt bool) error { b, err := io.ReadAll(os.Stdin) if err != nil { return fmt.Errorf("failed to read vault: %w", err)