-
Notifications
You must be signed in to change notification settings - Fork 123
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PMM-13132 Encryption rotation. #3199
Open
JiriCtvrtka
wants to merge
52
commits into
PMM-13129-encryption
Choose a base branch
from
PMM-13132-encryption-rotation
base: PMM-13129-encryption
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+472
−50
Open
Changes from all commits
Commits
Show all changes
52 commits
Select commit
Hold shift + click to select a range
74edcb1
PMM-13132 Basics.
JiriCtvrtka 3e62767
PMM-13132 Some changes.
JiriCtvrtka 97bed88
PMM-13132 Make format.
JiriCtvrtka 50fead6
PMM-13132 Mod fix, tidy.
JiriCtvrtka fcf215d
PMM-13132 Fix.
JiriCtvrtka 57a2024
PMM-13132 Changes.
JiriCtvrtka 937bbcd
PMM-13132 Changes.
JiriCtvrtka 8961b3f
PMM-13132 Rotation.
JiriCtvrtka 0176934
PMM-13132 Format.
JiriCtvrtka 65d2234
PMM-13132 Changes.
JiriCtvrtka 782e82f
PMM-13132 Fix.
JiriCtvrtka 2cb54e1
PMM-13132 Backup and restore of previous key.
JiriCtvrtka b0ddeab
PMM-13132 Changes.
JiriCtvrtka ad3fec9
PMM-13132 Lint.
JiriCtvrtka cb5b6c5
Merge branch 'PMM-13129-encryption' into PMM-13132-encryption-rotation
JiriCtvrtka 50f0c83
PMM-13132 Correct message.
JiriCtvrtka 07edcc7
PMM-13132 Changes related to tests.
JiriCtvrtka 4a0588b
Merge branch 'PMM-13129-encryption' into PMM-13132-encryption-rotation
JiriCtvrtka c8e275f
PMM-13132 Test for whole cycle.
JiriCtvrtka 8107431
PMM-13132 Handle OS interuptions.
JiriCtvrtka a60eda2
PMM-13132 Lint.
JiriCtvrtka 3474974
PMM-13132 Lint.
JiriCtvrtka 7e58301
PMM-13132 Logger and logs.
JiriCtvrtka e8f94bf
PMM-13132 Test DB.
JiriCtvrtka 5fb3fe6
Revert "PMM-13132 Test DB."
JiriCtvrtka 977c64f
PMM-13132 Changes, CI.
JiriCtvrtka be0c4b7
Merge branch 'PMM-13129-encryption' into PMM-13132-encryption-rotation
JiriCtvrtka 7986a5b
PMM-13132 Fix in test.
JiriCtvrtka 236ade5
PMM-13132 Changes.
JiriCtvrtka d5e479d
PMM-13132 Skip encryption-rotation test in main test.
JiriCtvrtka 7ff24b6
PMM-13132 Basic makefile for encryption-rotation.
JiriCtvrtka f59d89c
PMM-13132 Remove duplicate defaults.
JiriCtvrtka 699f31e
PMM-13132 Changes in workflow.
JiriCtvrtka a047d3e
PMM-13132 Remove devcontainer from makefile.
JiriCtvrtka 45125df
PMM-13132 Add ENV variable for rotation key.
JiriCtvrtka 6f4a525
PMM-13132 Add PG.
JiriCtvrtka 5e6a3d8
PMM-13132 Remove user, pass in PG compose.
JiriCtvrtka fbc86a8
PMM-13132 Test of user.
JiriCtvrtka da0ff75
PMM-13132 Change path for test.
JiriCtvrtka ae7094f
PMM-13132 Test of simpler structure.
JiriCtvrtka e3d146a
PMM-13132 Another changes in structure.
JiriCtvrtka d38a8ca
PMM-13132 Another changes to simplify rotation.
JiriCtvrtka d978cc3
PMM-13132 Format.
JiriCtvrtka ec82c91
PMM-13132 Improvements.
JiriCtvrtka b13abe8
PMM-13132 Add command to makefile, lint.
JiriCtvrtka 7aeaec5
PMM-13132 Lint.
JiriCtvrtka 096fc93
PMM-13132 Lint.
JiriCtvrtka 229e08a
PMM-13132 Wrappers around default on newly added methods.
JiriCtvrtka 89692ac
PMM-13132 Move into cmd of pmm-managed.
JiriCtvrtka f603530
PMM-13132 Suggested refactor.
JiriCtvrtka 7fab00f
PMM-13132 Another suggested refactor.
JiriCtvrtka 8a86a53
PMM-13132 Fix.
JiriCtvrtka File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
// Copyright (C) 2023 Percona LLC | ||
// | ||
// This program is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU Affero General Public License as published by | ||
// the Free Software Foundation, either version 3 of the License, or | ||
// (at your option) any later version. | ||
// | ||
// This program is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU Affero General Public License for more details. | ||
// | ||
// You should have received a copy of the GNU Affero General Public License | ||
// along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
// Package main is the main package for encryption keys rotation. | ||
package main | ||
|
||
import ( | ||
"os" | ||
"os/signal" | ||
"syscall" | ||
|
||
"github.com/Percona-Lab/kingpin" | ||
"github.com/sirupsen/logrus" | ||
|
||
"github.com/percona/pmm/managed/models" | ||
"github.com/percona/pmm/utils/logger" | ||
) | ||
|
||
func main() { | ||
signal.Ignore(syscall.SIGINT, syscall.SIGTERM) // to prevent any interuptions during process | ||
|
||
logger.SetupGlobalLogger() | ||
|
||
sqlDB, err := models.OpenDB(setupParams()) | ||
if err != nil { | ||
logrus.Error(err) | ||
os.Exit(1) | ||
} | ||
|
||
statusCode := models.RotateEncryptionKey(sqlDB, "pmm-managed") | ||
sqlDB.Close() //nolint:errcheck | ||
|
||
os.Exit(statusCode) | ||
} | ||
|
||
func setupParams() models.SetupDBParams { | ||
postgresAddrF := kingpin.Flag("postgres-addr", "PostgreSQL address"). | ||
Default(models.DefaultPostgreSQLAddr). | ||
Envar("PMM_POSTGRES_ADDR"). | ||
String() | ||
postgresDBNameF := kingpin.Flag("postgres-name", "PostgreSQL database name"). | ||
Default("pmm-managed"). | ||
Envar("PMM_POSTGRES_DBNAME"). | ||
String() | ||
postgresDBUsernameF := kingpin.Flag("postgres-username", "PostgreSQL database username"). | ||
Default("pmm-managed"). | ||
Envar("PMM_POSTGRES_USERNAME"). | ||
String() | ||
postgresSSLModeF := kingpin.Flag("postgres-ssl-mode", "PostgreSQL SSL mode"). | ||
Default(models.DisableSSLMode). | ||
Envar("PMM_POSTGRES_SSL_MODE"). | ||
Enum(models.DisableSSLMode, models.RequireSSLMode, models.VerifyCaSSLMode, models.VerifyFullSSLMode) | ||
postgresSSLCAPathF := kingpin.Flag("postgres-ssl-ca-path", "PostgreSQL SSL CA root certificate path"). | ||
Envar("PMM_POSTGRES_SSL_CA_PATH"). | ||
String() | ||
postgresDBPasswordF := kingpin.Flag("postgres-password", "PostgreSQL database password"). | ||
Default("pmm-managed"). | ||
Envar("PMM_POSTGRES_DBPASSWORD"). | ||
String() | ||
postgresSSLKeyPathF := kingpin.Flag("postgres-ssl-key-path", "PostgreSQL SSL key path"). | ||
Envar("PMM_POSTGRES_SSL_KEY_PATH"). | ||
String() | ||
postgresSSLCertPathF := kingpin.Flag("postgres-ssl-cert-path", "PostgreSQL SSL certificate path"). | ||
Envar("PMM_POSTGRES_SSL_CERT_PATH"). | ||
String() | ||
|
||
kingpin.Parse() | ||
|
||
return models.SetupDBParams{ | ||
Address: *postgresAddrF, | ||
Name: *postgresDBNameF, | ||
Username: *postgresDBUsernameF, | ||
Password: *postgresDBPasswordF, | ||
SSLMode: *postgresSSLModeF, | ||
SSLCAPath: *postgresSSLCAPathF, | ||
SSLKeyPath: *postgresSSLKeyPathF, | ||
SSLCertPath: *postgresSSLCertPathF, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
// Copyright (C) 2023 Percona LLC | ||
// | ||
// This program is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU Affero General Public License as published by | ||
// the Free Software Foundation, either version 3 of the License, or | ||
// (at your option) any later version. | ||
// | ||
// This program is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU Affero General Public License for more details. | ||
// | ||
// You should have received a copy of the GNU Affero General Public License | ||
// along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
|
||
package models | ||
|
||
import ( | ||
"database/sql" | ||
"fmt" | ||
"os/exec" | ||
"strings" | ||
|
||
"github.com/pkg/errors" | ||
"github.com/sirupsen/logrus" | ||
"gopkg.in/reform.v1" | ||
"gopkg.in/reform.v1/dialects/postgresql" | ||
|
||
"github.com/percona/pmm/managed/utils/encryption" | ||
) | ||
|
||
// RotateEncryptionKey will stop PMM server, decrypt data, create new encryption key and encrypt them and start PMM Server again. | ||
func RotateEncryptionKey(sqlDB *sql.DB, dbName string) int { | ||
db := reform.NewDB(sqlDB, postgresql.Dialect, nil) | ||
|
||
err := stopPMMServer() | ||
if err != nil { | ||
logrus.Errorf("Failed to stop PMM Server: %+v", err) | ||
return 2 | ||
} | ||
|
||
err = rotateEncryptionKey(db, dbName) | ||
if err != nil { | ||
logrus.Errorf("Failed to rotate encryption key: %+v", err) | ||
return 3 | ||
} | ||
|
||
err = startPMMServer() | ||
if err != nil { | ||
logrus.Errorf("Failed to start PMM Server: %+v", err) | ||
return 4 | ||
} | ||
|
||
return 0 | ||
} | ||
|
||
func startPMMServer() error { | ||
if isPMMServerStatus("RUNNING") { | ||
return nil | ||
} | ||
|
||
cmd := exec.Command("supervisorctl", "start pmm-managed") | ||
output, err := cmd.CombinedOutput() | ||
if err != nil { | ||
return fmt.Errorf("%w: %s", err, output) | ||
} | ||
|
||
if !isPMMServerStatus("RUNNING") { | ||
return errors.New("cannot start pmm-managed") | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func stopPMMServer() error { | ||
if isPMMServerStatus("STOPPED") { | ||
return nil | ||
} | ||
|
||
cmd := exec.Command("supervisorctl", "stop pmm-managed") | ||
output, err := cmd.CombinedOutput() | ||
if err != nil { | ||
return fmt.Errorf("%w: %s", err, output) | ||
} | ||
|
||
if !isPMMServerStatus("STOPPED") { | ||
return errors.New("cannot stop pmm-managed") | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func isPMMServerStatus(status string) bool { | ||
cmd := exec.Command("supervisorctl", "status pmm-managed") | ||
output, _ := cmd.CombinedOutput() | ||
|
||
return strings.Contains(string(output), strings.ToUpper(status)) | ||
} | ||
|
||
func rotateEncryptionKey(db *reform.DB, dbName string) error { | ||
return db.InTransaction(func(tx *reform.TX) error { | ||
logrus.Infof("DB %s is being decrypted", dbName) | ||
err := DecryptDB(tx, dbName, DefaultAgentEncryptionColumns) | ||
if err != nil { | ||
return err | ||
} | ||
logrus.Infof("DB %s is successfully decrypted", dbName) | ||
|
||
logrus.Infoln("Rotating encryption key") | ||
err = encryption.RotateEncryptionKey() | ||
if err != nil { | ||
return err | ||
} | ||
logrus.Infof("New encryption key generated") | ||
|
||
logrus.Infof("DB %s is being encrypted", dbName) | ||
err = EncryptDB(tx, dbName, DefaultAgentEncryptionColumns) | ||
if err != nil { | ||
if e := encryption.RestoreOldEncryptionKey(); e != nil { | ||
return errors.Wrap(err, e.Error()) | ||
} | ||
return err | ||
} | ||
logrus.Infof("DB %s is successfully encrypted", dbName) | ||
|
||
return nil | ||
}) | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's append column to
prepared
. anyway we do it inaddToEncryptedItems