Skip to content

Commit 82eca75

Browse files
FEATURE (security): Clean PostgreSQL creds after restore
1 parent 5186643 commit 82eca75

File tree

8 files changed

+50
-27
lines changed

8 files changed

+50
-27
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,12 @@
5858
- **SSL support**: Secure connections available
5959
- **Easy restoration**: One-click restore from any backup
6060

61-
### 🔒 **Backup Encryption** <a href="https://postgresus.com/encryption">(docs)</a>
61+
### 🔒 **Enterprise-grade security** <a href="https://postgresus.com/security">(docs)</a>
6262

6363
- **AES-256-GCM encryption**: Enterprise-grade protection for backup files
64-
- **Zero-trust storage**: Encrypted backups are useless so you can keep in shared storages like S3, Azure Blob Storage, etc.
65-
- **Optionality**: Encrypted backups are optional and can be enabled or disabled if you wish
66-
- **Download unencrypted**: You can still download unencrypted backups via the 'Download' button to use them in `pg_restore` or other tools.
64+
- **Zero-trust storage**: Backups are encrypted and they are useless to attackers, so you can keep them in shared storages like S3, Azure Blob Storage, etc.
65+
- **Encryption for secrets**: Any sensitive data is encrypted and never exposed, even in logs or error messages
66+
- **Read-only user**: Postgresus uses by default a read-only user for backups and never stores anything that can change your data
6767

6868
### 👥 **Suitable for Teams** <a href="https://postgresus.com/access-management">(docs)</a>
6969

backend/internal/features/databases/databases/postgresql/model.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ type PostgresqlDatabase struct {
1919
ID uuid.UUID `json:"id" gorm:"primaryKey;type:uuid;default:gen_random_uuid()"`
2020

2121
DatabaseID *uuid.UUID `json:"databaseId" gorm:"type:uuid;column:database_id"`
22-
RestoreID *uuid.UUID `json:"restoreId" gorm:"type:uuid;column:restore_id"`
2322

2423
Version tools.PostgresqlVersion `json:"version" gorm:"type:text;not null"`
2524

backend/internal/features/restores/models/model.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package models
22

33
import (
44
"postgresus-backend/internal/features/backups/backups"
5-
"postgresus-backend/internal/features/databases/databases/postgresql"
65
"postgresus-backend/internal/features/restores/enums"
76
"time"
87

@@ -16,8 +15,6 @@ type Restore struct {
1615
BackupID uuid.UUID `json:"backupId" gorm:"column:backup_id;type:uuid;not null"`
1716
Backup *backups.Backup
1817

19-
Postgresql *postgresql.PostgresqlDatabase `json:"postgresql,omitempty" gorm:"foreignKey:RestoreID"`
20-
2118
FailMessage *string `json:"failMessage" gorm:"column:fail_message"`
2219

2320
RestoreDurationMs int64 `json:"restoreDurationMs" gorm:"column:restore_duration_ms;default:0"`

backend/internal/features/restores/repository.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ func (r *RestoreRepository) FindByBackupID(backupID uuid.UUID) ([]*models.Restor
3232
if err := storage.
3333
GetDb().
3434
Preload("Backup").
35-
Preload("Postgresql").
3635
Where("backup_id = ?", backupID).
3736
Order("created_at DESC").
3837
Find(&restores).Error; err != nil {
@@ -48,7 +47,6 @@ func (r *RestoreRepository) FindByID(id uuid.UUID) (*models.Restore, error) {
4847
if err := storage.
4948
GetDb().
5049
Preload("Backup").
51-
Preload("Postgresql").
5250
Where("id = ?", id).
5351
First(&restore).Error; err != nil {
5452
return nil, err
@@ -63,7 +61,6 @@ func (r *RestoreRepository) FindByStatus(status enums.RestoreStatus) ([]*models.
6361
if err := storage.
6462
GetDb().
6563
Preload("Backup").
66-
Preload("Postgresql").
6764
Where("status = ?", status).
6865
Order("created_at DESC").
6966
Find(&restores).Error; err != nil {

backend/internal/features/restores/service.go

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -191,15 +191,9 @@ func (s *RestoreService) RestoreBackup(
191191
return err
192192
}
193193

194-
// Set the RestoreID on the PostgreSQL database and save it
195-
if requestDTO.PostgresqlDatabase != nil {
196-
requestDTO.PostgresqlDatabase.RestoreID = &restore.ID
197-
restore.Postgresql = requestDTO.PostgresqlDatabase
198-
199-
// Save the restore again to include the postgresql database
200-
if err := s.restoreRepository.Save(&restore); err != nil {
201-
return err
202-
}
194+
// Save the restore again to include the postgresql database
195+
if err := s.restoreRepository.Save(&restore); err != nil {
196+
return err
203197
}
204198

205199
storage, err := s.storageService.GetStorageByID(backup.StorageID)
@@ -216,10 +210,15 @@ func (s *RestoreService) RestoreBackup(
216210

217211
start := time.Now().UTC()
218212

213+
restoringToDB := &databases.Database{
214+
Postgresql: requestDTO.PostgresqlDatabase,
215+
}
216+
219217
err = s.restoreBackupUsecase.Execute(
220218
backupConfig,
221219
restore,
222220
database,
221+
restoringToDB,
223222
backup,
224223
storage,
225224
)

backend/internal/features/restores/usecases/postgresql/restore_backup_uc.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,14 @@ type RestorePostgresqlBackupUsecase struct {
3636
}
3737

3838
func (uc *RestorePostgresqlBackupUsecase) Execute(
39-
database *databases.Database,
39+
originalDB *databases.Database,
40+
restoringToDB *databases.Database,
4041
backupConfig *backups_config.BackupConfig,
4142
restore models.Restore,
4243
backup *backups.Backup,
4344
storage *storages.Storage,
4445
) error {
45-
if database.Type != databases.DatabaseTypePostgres {
46+
if originalDB.Type != databases.DatabaseTypePostgres {
4647
return errors.New("database type not supported")
4748
}
4849

@@ -54,7 +55,7 @@ func (uc *RestorePostgresqlBackupUsecase) Execute(
5455
backup.ID,
5556
)
5657

57-
pg := restore.Postgresql
58+
pg := restoringToDB.Postgresql
5859
if pg == nil {
5960
return fmt.Errorf("postgresql configuration is required for restore")
6061
}
@@ -83,7 +84,7 @@ func (uc *RestorePostgresqlBackupUsecase) Execute(
8384
}
8485

8586
return uc.restoreFromStorage(
86-
database,
87+
originalDB,
8788
tools.GetPostgresqlExecutable(
8889
pg.Version,
8990
"pg_restore",

backend/internal/features/restores/usecases/restore_backup_uc.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@ type RestoreBackupUsecase struct {
1717
func (uc *RestoreBackupUsecase) Execute(
1818
backupConfig *backups_config.BackupConfig,
1919
restore models.Restore,
20-
database *databases.Database,
20+
originalDB *databases.Database,
21+
restoringToDB *databases.Database,
2122
backup *backups.Backup,
2223
storage *storages.Storage,
2324
) error {
24-
if database.Type == databases.DatabaseTypePostgres {
25+
if originalDB.Type == databases.DatabaseTypePostgres {
2526
return uc.restorePostgresqlBackupUsecase.Execute(
26-
database,
27+
originalDB,
28+
restoringToDB,
2729
backupConfig,
2830
restore,
2931
backup,
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
-- +goose Up
2+
-- +goose StatementBegin
3+
4+
ALTER TABLE postgresql_databases
5+
DROP CONSTRAINT IF EXISTS fk_postgresql_databases_restore_id;
6+
7+
DROP INDEX IF EXISTS idx_postgresql_databases_restore_id;
8+
9+
ALTER TABLE postgresql_databases
10+
DROP COLUMN IF EXISTS restore_id;
11+
12+
-- +goose StatementEnd
13+
14+
-- +goose Down
15+
-- +goose StatementBegin
16+
17+
ALTER TABLE postgresql_databases
18+
ADD COLUMN restore_id UUID;
19+
20+
CREATE INDEX idx_postgresql_databases_restore_id ON postgresql_databases (restore_id);
21+
22+
ALTER TABLE postgresql_databases
23+
ADD CONSTRAINT fk_postgresql_databases_restore_id
24+
FOREIGN KEY (restore_id)
25+
REFERENCES restores (id)
26+
ON DELETE CASCADE;
27+
28+
-- +goose StatementEnd

0 commit comments

Comments
 (0)