Skip to content
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-9947: Encryption #897

Closed
wants to merge 9 commits into from
Closed

PMM-9947: Encryption #897

wants to merge 9 commits into from

Conversation

ritbl
Copy link
Contributor

@ritbl ritbl commented May 17, 2022

@ritbl ritbl force-pushed the PMM-9947-encryption branch from d949477 to 79ae423 Compare June 3, 2022 10:32
var privateKey []byte

//go:embed test.pub
var publicKey []byte
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci-lint] reported by reviewdog 🐶
publicKey is unused (deadcode)

assert.Nil(t, err)
textWithEmbeddedBlock := fmt.Sprintf("--arg=%s", block)

fmt.Println(textWithEmbeddedBlock)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci-lint] reported by reviewdog 🐶
use of fmt.Println forbidden by pattern ^(fmt\.Print(|f|ln)|print|println)$ (forbidigo)

var publicKey []byte

func TestDecryptEmbeddedWithFormat(t *testing.T) {
key := "key1"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci-lint] reported by reviewdog 🐶
string key1 has 3 occurrences, make it a constant (goconst)


// extract key
bodyStart := strings.Index(text, EncryptedTextBlockCipherStart)
key := text[:bodyStart]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci-lint] reported by reviewdog 🐶
offBy1: Index() can return -1; maybe you wanted to do text[:bodyStart+1] (gocritic)

@@ -0,0 +1,293 @@
package rsa_encryptor
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci-lint] reported by reviewdog 🐶
don't use an underscore in package name (golint)

Type: "PUBLIC KEY",
Bytes: publicKeyBytes,
}
publicPem, err := os.Create(publicKeyPath)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci-lint] reported by reviewdog 🐶
G304: Potential file inclusion via variable (gosec)

}, nil
}

func (s *Service) DecryptDsn(dsn string) (string, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci-lint] reported by reviewdog 🐶
exported: exported method Service.DecryptDsn should have comment or be unexported (revive)

}
privateKeyPem, err := os.Create(privateKeyPath)
if err != nil {
return errors.Wrapf(err, "Error when create [%s]: %s \n", privateKeyPath, err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci-lint] reported by reviewdog 🐶
error-strings: error strings should not be capitalized or end with punctuation or a newline (revive)

}
err = privateKeyPem.Chmod(perm)
if err != nil {
return errors.Wrapf(err, "Error when changing file permissions [%s]: %s \n", privateKeyPath, err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci-lint] reported by reviewdog 🐶
error-strings: error strings should not be capitalized or end with punctuation or a newline (revive)

}
err = pem.Encode(privateKeyPem, privateKeyBlock)
if err != nil {
return errors.Wrapf(err, "Error when encode private pem: %s \n", err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci-lint] reported by reviewdog 🐶
error-strings: error strings should not be capitalized or end with punctuation or a newline (revive)

Copy link
Member

@BupycHuk BupycHuk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, finally I found a time to review this PR. Sorry for that.
How are we going to share public and private keys between pmm-admin and pmm-agent? Are we going to inject them during the build of PMM or just store them in repository or generate them on PMM managed side and share accross clients?
If we will store them in repository than still it's not secure. pmm-admin allows to add agents to another host and if pmm-agent on another host doesn't support ecryption we will have a problem.
If we will inject keys during build we should disable encryption by default for builds made by community to not have problems with compatability.

Tests are failing. Please fix them.
Please fix linters as well.

@@ -150,6 +157,13 @@ func (cmd *addMongoDBCommand) Run() (commands.Result, error) {
}
}

encryptor := rsa_encryptor.GetEncryptor(ctx)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we pass the encryptor instead of passing context and trying to extract the encryptor from context. As far as I see there is no check for the existence of an encryptor and that's why your tests are failing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll fix the tests

type Formatter func(string) string

// Service provides RSA encryption interface for sensitive data.
type Service struct {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we call it Encryptor?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Too many public methods, let's make methods private if we don't use them outside of this package.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we call it Encryptor?
ok

Too many public methods, let's make methods private if we don't use them outside of this package.
What method/methods you think should be made private?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I was clear here. All methods are not used outside of this package.

}

// GenerateKeys creates asymmetric keys.
func (s *Service) GenerateKeys(privateKeyPath, publicKeyPath string, bits int, perm fs.FileMode) error {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any usage of this method.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should it be a method at all? looks like it can be just a function

utils/rsa_encryptor/encryptor.go Outdated Show resolved Hide resolved
"github.com/pkg/errors"
)

const (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need all these constants be public?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. Will make them private

@ritbl ritbl requested a review from BupycHuk June 20, 2022 06:35
@ritbl
Copy link
Contributor Author

ritbl commented Jun 20, 2022

@BupycHuk

How are we going to share public and private keys between pmm-admin and pmm-agent?

We have multiple options:
1: Leave as it is in this PR - anyone with a bit of patience can find all the keys and decrypt data
Security: 1 out of 5 (very bad). Just grab the keys from repo....
Ease of change / backward compatibility: 5 out of 5 (great).

2: Inject keys in the build time. Someone needs to generate keys and put in secrets in the repo.
Security: 2 out of 5 (bad). Keys will be embedded. It will make harder to get the key but it is still very easy.
Ease of change / backward compatibility: 4 out of 5 (good)

3: Inject keys before pmm starts.
Security: 3-4 out of 5 (good). Proper solution will take time and client now need to manage the keys. It can be make semi-transparent, but still it will require a lot more work.
Ease of change / backward compatibility: 1 out of 5 (very bad)

We can start with any of these, the key can be rotated later. I think any solution would be better if we compare it with the current one.

by default for builds made by community to not have problems with compatability

Actually, it is not needed. It will all work. It is backward compatible. We can start with key being even stored in source code (just because it is easy). Later we can provide better key management solution and create simple rotation job. The key name is embedded into metadata, so that we can have multiple keys.

@BupycHuk
Copy link
Member

pmm-admin allows to add agents to another host; if pmm-agent on another host doesn't support encryption, we will have a problem.
it's not a typical case, but it's still possible.

@ritbl
Copy link
Contributor Author

ritbl commented Jun 20, 2022

@BupycHuk

pmm-admin allows to add agents to another host; if pmm-agent on another host doesn't support encryption, we will have a problem.
it's not a typical case, but it's still possible.

Admin perform encryption, for that public key is used. It doesn't need to be kept in secret.
We can embed public key and even put in the source code. Only private key should be taken care of (agent).

@ritbl ritbl changed the title PMM-9947: Encryption PoC PMM-9947: Encryption Jun 20, 2022
@artemgavrilov
Copy link
Contributor

@BupycHuk @ritbl
To be honest I have feeling that this kind of protection should be done on different level. I think it's responsibility of a system administrator to setup TLS certificates for PMM server and we should just respect these settings. This is more obvious and typical solution than custom encryption of just passwords (other information may be sensitive as well). To prevent passwords leaking to logs we can just make codebase audit.

Options 1 and 2 have no sense, it's increasing complexity with almost zero profit. Option 3 may work, but again system administrator should take care for keys management. For now I thinks we can notify user in logs/UI that connection is insecure and ask him to setup TLS.

@ademidoff ademidoff marked this pull request as draft September 16, 2022 08:45
Copy link
Member

@ademidoff ademidoff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ritbl Do you mind if I convert it to draft to suppress notifications?

@BupycHuk BupycHuk closed this Jun 7, 2023
@BupycHuk BupycHuk deleted the PMM-9947-encryption branch June 7, 2023 21:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants