feat(GODT-2509): Migrate TLS cert from v1/v2 location during upgrade to v3
This commit is contained in:
parent
3ca5d0af71
commit
4e7acd9091
|
@ -87,6 +87,11 @@ func migrateOldSettings(v *vault.Vault) error {
|
||||||
return fmt.Errorf("failed to get user config dir: %w", err)
|
return fmt.Errorf("failed to get user config dir: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return migrateOldSettingsWithDir(configDir, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// nolint:gosec
|
||||||
|
func migrateOldSettingsWithDir(configDir string, v *vault.Vault) error {
|
||||||
b, err := os.ReadFile(filepath.Join(configDir, "protonmail", "bridge", "prefs.json"))
|
b, err := os.ReadFile(filepath.Join(configDir, "protonmail", "bridge", "prefs.json"))
|
||||||
if errors.Is(err, fs.ErrNotExist) {
|
if errors.Is(err, fs.ErrNotExist) {
|
||||||
return nil
|
return nil
|
||||||
|
@ -94,7 +99,27 @@ func migrateOldSettings(v *vault.Vault) error {
|
||||||
return fmt.Errorf("failed to read old prefs file: %w", err)
|
return fmt.Errorf("failed to read old prefs file: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return migratePrefsToVault(v, b)
|
if err := migratePrefsToVault(v, b); err != nil {
|
||||||
|
return fmt.Errorf("failed to migrate prefs to vault: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
logrus.Info("Migrating TLS certificate")
|
||||||
|
|
||||||
|
certPEM, err := os.ReadFile(filepath.Join(configDir, "protonmail", "bridge", "cert.pem"))
|
||||||
|
if errors.Is(err, fs.ErrNotExist) {
|
||||||
|
return nil
|
||||||
|
} else if err != nil {
|
||||||
|
return fmt.Errorf("failed to read old cert file: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
keyPEM, err := os.ReadFile(filepath.Join(configDir, "protonmail", "bridge", "key.pem"))
|
||||||
|
if errors.Is(err, fs.ErrNotExist) {
|
||||||
|
return nil
|
||||||
|
} else if err != nil {
|
||||||
|
return fmt.Errorf("failed to read old key file: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return v.SetBridgeTLSCertKey(certPEM, keyPEM)
|
||||||
}
|
}
|
||||||
|
|
||||||
func migrateOldAccounts(locations *locations.Locations, v *vault.Vault) error {
|
func migrateOldAccounts(locations *locations.Locations, v *vault.Vault) error {
|
||||||
|
|
|
@ -38,53 +38,44 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMigratePrefsToVault(t *testing.T) {
|
func TestMigratePrefsToVaultWithKeys(t *testing.T) {
|
||||||
// Create a new vault.
|
// Create a new vault.
|
||||||
vault, corrupt, err := vault.New(t.TempDir(), t.TempDir(), []byte("my secret key"))
|
vault, corrupt, err := vault.New(t.TempDir(), t.TempDir(), []byte("my secret key"))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.False(t, corrupt)
|
require.False(t, corrupt)
|
||||||
|
|
||||||
// load the old prefs file.
|
// load the old prefs file.
|
||||||
b, err := os.ReadFile(filepath.Join("testdata", "prefs.json"))
|
configDir := filepath.Join("testdata", "with_keys")
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Migrate the old prefs file to the new vault.
|
// Migrate the old prefs file to the new vault.
|
||||||
require.NoError(t, migratePrefsToVault(vault, b))
|
require.NoError(t, migrateOldSettingsWithDir(configDir, vault))
|
||||||
|
|
||||||
// Check that the IMAP and SMTP prefs are migrated.
|
// Check Json Settings
|
||||||
require.Equal(t, 2143, vault.GetIMAPPort())
|
validateJSONPrefs(t, vault)
|
||||||
require.Equal(t, 2025, vault.GetSMTPPort())
|
|
||||||
require.True(t, vault.GetSMTPSSL())
|
|
||||||
|
|
||||||
// Check that the update channel is migrated.
|
// Check the keys were found and collected.
|
||||||
require.True(t, vault.GetAutoUpdate())
|
require.Equal(t, "-----BEGIN CERTIFICATE-----", string(vault.GetBridgeTLSCert()))
|
||||||
require.Equal(t, updater.EarlyChannel, vault.GetUpdateChannel())
|
require.Equal(t, "-----BEGIN RSA PRIVATE KEY-----", string(vault.GetBridgeTLSKey()))
|
||||||
require.Equal(t, 0.4849529004202015, vault.GetUpdateRollout())
|
}
|
||||||
|
|
||||||
// Check that the app settings have been migrated.
|
func TestMigratePrefsToVaultWithoutKeys(t *testing.T) {
|
||||||
require.False(t, vault.GetFirstStart())
|
// Create a new vault.
|
||||||
require.Equal(t, "blablabla", vault.GetColorScheme())
|
vault, corrupt, err := vault.New(t.TempDir(), t.TempDir(), []byte("my secret key"))
|
||||||
require.Equal(t, "2.3.0+git", vault.GetLastVersion().String())
|
|
||||||
require.True(t, vault.GetAutostart())
|
|
||||||
|
|
||||||
// Check that the other app settings have been migrated.
|
|
||||||
require.Equal(t, 16, vault.SyncWorkers())
|
|
||||||
require.Equal(t, 16, vault.SyncAttPool())
|
|
||||||
require.False(t, vault.GetProxyAllowed())
|
|
||||||
require.False(t, vault.GetShowAllMail())
|
|
||||||
|
|
||||||
// Check that the cookies have been migrated.
|
|
||||||
jar, err := cookiejar.New(nil)
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
require.False(t, corrupt)
|
||||||
|
|
||||||
cookies, err := cookies.NewCookieJar(jar, vault)
|
// load the old prefs file.
|
||||||
require.NoError(t, err)
|
configDir := filepath.Join("testdata", "without_keys")
|
||||||
|
|
||||||
url, err := url.Parse("https://api.protonmail.ch")
|
// Migrate the old prefs file to the new vault.
|
||||||
require.NoError(t, err)
|
require.NoError(t, migrateOldSettingsWithDir(configDir, vault))
|
||||||
|
|
||||||
// There should be a cookie for the API.
|
// Check Json Settings
|
||||||
require.NotEmpty(t, cookies.Cookies(url))
|
validateJSONPrefs(t, vault)
|
||||||
|
|
||||||
|
// Check the keys were found and collected.
|
||||||
|
require.NotEqual(t, []byte("-----BEGIN CERTIFICATE-----"), vault.GetBridgeTLSCert())
|
||||||
|
require.NotEqual(t, []byte("-----BEGIN RSA PRIVATE KEY-----"), vault.GetBridgeTLSKey())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestKeychainMigration(t *testing.T) {
|
func TestKeychainMigration(t *testing.T) {
|
||||||
|
@ -101,7 +92,7 @@ func TestKeychainMigration(t *testing.T) {
|
||||||
oldCacheDir := filepath.Join(tmpDir, "protonmail", "bridge")
|
oldCacheDir := filepath.Join(tmpDir, "protonmail", "bridge")
|
||||||
require.NoError(t, os.MkdirAll(oldCacheDir, 0o700))
|
require.NoError(t, os.MkdirAll(oldCacheDir, 0o700))
|
||||||
|
|
||||||
oldPrefs, err := os.ReadFile(filepath.Join("testdata", "prefs.json"))
|
oldPrefs, err := os.ReadFile(filepath.Join("testdata", "without_keys", "protonmail", "bridge", "prefs.json"))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.NoError(t, os.WriteFile(
|
require.NoError(t, os.WriteFile(
|
||||||
|
@ -196,3 +187,40 @@ func TestUserMigration(t *testing.T) {
|
||||||
require.Equal(t, vault.CombinedMode, u.AddressMode())
|
require.Equal(t, vault.CombinedMode, u.AddressMode())
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validateJSONPrefs(t *testing.T, vault *vault.Vault) {
|
||||||
|
// Check that the IMAP and SMTP prefs are migrated.
|
||||||
|
require.Equal(t, 2143, vault.GetIMAPPort())
|
||||||
|
require.Equal(t, 2025, vault.GetSMTPPort())
|
||||||
|
require.True(t, vault.GetSMTPSSL())
|
||||||
|
|
||||||
|
// Check that the update channel is migrated.
|
||||||
|
require.True(t, vault.GetAutoUpdate())
|
||||||
|
require.Equal(t, updater.EarlyChannel, vault.GetUpdateChannel())
|
||||||
|
require.Equal(t, 0.4849529004202015, vault.GetUpdateRollout())
|
||||||
|
|
||||||
|
// Check that the app settings have been migrated.
|
||||||
|
require.False(t, vault.GetFirstStart())
|
||||||
|
require.Equal(t, "blablabla", vault.GetColorScheme())
|
||||||
|
require.Equal(t, "2.3.0+git", vault.GetLastVersion().String())
|
||||||
|
require.True(t, vault.GetAutostart())
|
||||||
|
|
||||||
|
// Check that the other app settings have been migrated.
|
||||||
|
require.Equal(t, 16, vault.SyncWorkers())
|
||||||
|
require.Equal(t, 16, vault.SyncAttPool())
|
||||||
|
require.False(t, vault.GetProxyAllowed())
|
||||||
|
require.False(t, vault.GetShowAllMail())
|
||||||
|
|
||||||
|
// Check that the cookies have been migrated.
|
||||||
|
jar, err := cookiejar.New(nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
cookies, err := cookies.NewCookieJar(jar, vault)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
url, err := url.Parse("https://api.protonmail.ch")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// There should be a cookie for the API.
|
||||||
|
require.NotEmpty(t, cookies.Cookies(url))
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
|
@ -0,0 +1 @@
|
||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
|
@ -0,0 +1,31 @@
|
||||||
|
{
|
||||||
|
"allow_proxy": "false",
|
||||||
|
"attachment_workers": "16",
|
||||||
|
"autostart": "true",
|
||||||
|
"autoupdate": "true",
|
||||||
|
"cache_compression": "true",
|
||||||
|
"cache_concurrent_read": "16",
|
||||||
|
"cache_concurrent_write": "16",
|
||||||
|
"cache_enabled": "true",
|
||||||
|
"cache_location": "/home/user/.config/protonmail/bridge/cache/c11/messages",
|
||||||
|
"cache_min_free_abs": "250000000",
|
||||||
|
"cache_min_free_rat": "",
|
||||||
|
"color_scheme": "blablabla",
|
||||||
|
"cookies": "{\"https://api.protonmail.ch\":[{\"Name\":\"Session-Id\",\"Value\":\"blablablablablablablablabla\",\"Path\":\"/\",\"Domain\":\"protonmail.ch\",\"Expires\":\"2023-02-19T00:20:40.269424437+01:00\",\"RawExpires\":\"\",\"MaxAge\":7776000,\"Secure\":true,\"HttpOnly\":true,\"SameSite\":0,\"Raw\":\"Session-Id=blablablablablablablablabla; Domain=protonmail.ch; Path=/; HttpOnly; Secure; Max-Age=7776000\",\"Unparsed\":null},{\"Name\":\"Tag\",\"Value\":\"default\",\"Path\":\"/\",\"Domain\":\"\",\"Expires\":\"2023-02-19T00:20:40.269428627+01:00\",\"RawExpires\":\"\",\"MaxAge\":7776000,\"Secure\":true,\"HttpOnly\":false,\"SameSite\":0,\"Raw\":\"Tag=default; Path=/; Secure; Max-Age=7776000\",\"Unparsed\":null}],\"https://protonmail.com\":[{\"Name\":\"Session-Id\",\"Value\":\"blablablablablablablablabla\",\"Path\":\"/\",\"Domain\":\"protonmail.com\",\"Expires\":\"2023-02-19T00:20:18.315084712+01:00\",\"RawExpires\":\"\",\"MaxAge\":7776000,\"Secure\":true,\"HttpOnly\":true,\"SameSite\":0,\"Raw\":\"Session-Id=Y3q2Mh-ClvqL6LWeYdfyPgAAABI; Domain=protonmail.com; Path=/; HttpOnly; Secure; Max-Age=7776000\",\"Unparsed\":null},{\"Name\":\"Tag\",\"Value\":\"redirect\",\"Path\":\"/\",\"Domain\":\"\",\"Expires\":\"2023-02-19T00:20:18.315087646+01:00\",\"RawExpires\":\"\",\"MaxAge\":7776000,\"Secure\":true,\"HttpOnly\":false,\"SameSite\":0,\"Raw\":\"Tag=redirect; Path=/; Secure; Max-Age=7776000\",\"Unparsed\":null}]}",
|
||||||
|
"fetch_workers": "16",
|
||||||
|
"first_time_start": "false",
|
||||||
|
"first_time_start_gui": "true",
|
||||||
|
"imap_workers": "16",
|
||||||
|
"is_all_mail_visible": "false",
|
||||||
|
"last_heartbeat": "325",
|
||||||
|
"last_used_version": "2.3.0+git",
|
||||||
|
"preferred_keychain": "secret-service",
|
||||||
|
"rebranding_migrated": "true",
|
||||||
|
"report_outgoing_email_without_encryption": "false",
|
||||||
|
"rollout": "0.4849529004202015",
|
||||||
|
"user_port_api": "1042",
|
||||||
|
"update_channel": "early",
|
||||||
|
"user_port_imap": "2143",
|
||||||
|
"user_port_smtp": "2025",
|
||||||
|
"user_ssl_smtp": "true"
|
||||||
|
}
|
|
@ -25,6 +25,14 @@ func (vault *Vault) GetBridgeTLSKey() []byte {
|
||||||
return vault.get().Certs.Bridge.Key
|
return vault.get().Certs.Bridge.Key
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetBridgeTLSCertKey sets the path to PEM-encoded certificates for the bridge.
|
||||||
|
func (vault *Vault) SetBridgeTLSCertKey(cert, key []byte) error {
|
||||||
|
return vault.mod(func(data *Data) {
|
||||||
|
data.Certs.Bridge.Cert = cert
|
||||||
|
data.Certs.Bridge.Key = key
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (vault *Vault) GetCertsInstalled() bool {
|
func (vault *Vault) GetCertsInstalled() bool {
|
||||||
return vault.get().Certs.Installed
|
return vault.get().Certs.Installed
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue