-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Add caching_sha2_password RSA public-key authentication #6017
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
Merged
Merged
Changes from 1 commit
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
cd642d9
feat(auth): add caching_sha2_password RSA key exchange
renecannao f5f4794
fix: persist rejected caching SHA-2 RSA config
renecannao c7ae9cb
fix: avoid double counting rejected RSA config
renecannao a8f0114
fix: harden caching SHA-2 RSA buffers
renecannao 346cf3b
fix: retain RSA plaintext allocation for cleansing
renecannao 958dff5
fix: harden auth packet construction
renecannao c2a05a5
chore: untrack task 3 report
renecannao 875fa65
fix: remediate caching SHA-2 RSA quality findings
renecannao 3f8bac9
fix: initialize protocol auth failure fields
renecannao 1a8ff95
docs: clarify RSA auth helper contracts
renecannao c38d04e
test: escape wildcard TAP descriptions
renecannao bb74515
test: align RSA rejection E2E with Admin refresh
renecannao 27b853d
fix: wait for in-flight RSA key publication
renecannao 9a3fe88
fix: serialize admin MySQL variable commits
renecannao d484a5e
test: make RSA publication race deterministic
renecannao 0d1c9f5
fix: address Sonar RSA review findings
renecannao 855abce
Merge remote-tracking branch 'origin/v3.0' into feature/caching-sha2-…
renecannao ba03b99
test: gate caching SHA-2 RSA expectations by version
renecannao 8870c4f
test: address final CodeRabbit findings
renecannao 2fdc294
Merge remote-tracking branch 'origin/v3.0' into feature/caching-sha2-…
renecannao 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
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or 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,97 @@ | ||
| # RSA key exchange for `caching_sha2_password` | ||
|
|
||
| ProxySQL 3.1 can authenticate MySQL clients that use | ||
| `caching_sha2_password` over a non-TLS frontend connection. When full | ||
| authentication is required, the client can request ProxySQL's RSA public key, | ||
| encrypt its password, and send the ciphertext back to ProxySQL. | ||
|
|
||
| TLS remains the recommended configuration. Requesting a public key over an | ||
| unauthenticated connection encrypts the password on the wire, but it does not | ||
| authenticate the ProxySQL server and is vulnerable to public-key substitution | ||
| by an active network attacker. Use TLS when server identity and transport | ||
| integrity are required. | ||
|
|
||
| ## Configuration | ||
|
|
||
| The following MySQL variables are available in ProxySQL 3.1 and later: | ||
|
|
||
| | Variable | Default | Description | | ||
| | --- | --- | --- | | ||
| | `mysql-caching_sha2_password_auto_generate_rsa_keys` | `true` | Generate a 2048-bit RSA pair when both configured files are absent. | | ||
| | `mysql-caching_sha2_password_private_key_path` | `proxysql-caching-sha2-private-key.pem` | Private-key path. A relative path is resolved below ProxySQL's data directory. | | ||
| | `mysql-caching_sha2_password_public_key_path` | `proxysql-caching-sha2-public-key.pem` | Public-key path. A relative path is resolved below ProxySQL's data directory. | | ||
|
|
||
| Apply changes with: | ||
|
|
||
| ```sql | ||
| LOAD MYSQL VARIABLES TO RUNTIME; | ||
| ``` | ||
|
|
||
| The three variables form one configuration unit. ProxySQL validates or | ||
| generates the complete pair before publishing it to frontend sessions. If a | ||
| reload fails, all three runtime values and the previously loaded key snapshot | ||
| remain unchanged. | ||
|
|
||
| Relative paths must stay beneath ProxySQL's data directory. Empty, `.` and | ||
| `..` components are rejected, and every parent directory is opened without | ||
| following symbolic links. Absolute paths are allowed when keys are managed in | ||
| another operator-controlled directory. | ||
|
|
||
| ## Key formats and permissions | ||
|
|
||
| The private key must be an unencrypted PKCS#8 PEM RSA private key (the PEM | ||
| header is `BEGIN PRIVATE KEY`). Traditional PKCS#1 (`BEGIN RSA PRIVATE KEY`) | ||
| and encrypted private keys are rejected. The public key must be a PEM | ||
| SubjectPublicKeyInfo public key. The two files must contain a structurally | ||
| valid matching RSA pair of at least 2048 bits. | ||
|
|
||
| The private file must be a regular file and must not grant any group or other | ||
| permissions. Generated files use these modes: | ||
|
|
||
| - private key: `0600` | ||
| - public key: `0644` | ||
|
|
||
| Encrypted private keys are not supported because ProxySQL has no runtime | ||
| passphrase input for this feature. | ||
|
|
||
| If the compiled default pair is unusable during initial runtime loading and | ||
| cannot be regenerated safely, ProxySQL records an explicit TLS-only state | ||
| (automatic generation off and both paths empty). TLS authentication remains | ||
| available, while RSA public-key authentication stays disabled until a valid | ||
| pair is loaded. | ||
|
|
||
| Automatic generation occurs only when both paths are absent. If exactly one | ||
| file exists, ProxySQL reports a configuration error and does not overwrite or | ||
| replace either path. Generation uses temporary files and no-overwrite | ||
| publication so concurrent ProxySQL processes cannot publish a mixed pair. | ||
|
|
||
| ## Reload and cluster behavior | ||
|
|
||
| Each authentication exchange retains the same immutable key snapshot from the | ||
| public-key response through RSA decryption. A concurrent | ||
| `LOAD MYSQL VARIABLES TO RUNTIME` can therefore rotate keys without breaking | ||
| an exchange already in progress. | ||
|
|
||
| Cluster synchronization transfers the variable values, not private-key | ||
| contents. Every ProxySQL node must be able to read its configured local pair, | ||
| or generate its own pair when automatic generation is enabled. Do not store | ||
| private-key contents in the ProxySQL configuration database. | ||
|
|
||
| ## Client behavior and failures | ||
|
|
||
| The client must use `caching_sha2_password`, disable TLS only when intended, | ||
| and enable its server-public-key request option. For Oracle's MySQL CLI: | ||
|
|
||
| ```bash | ||
| mysql --default-auth=caching_sha2_password \ | ||
| --ssl-mode=DISABLED --get-server-public-key \ | ||
| --host=127.0.0.1 --port=6033 --user=app --password | ||
| ``` | ||
|
|
||
| ProxySQL implements the MySQL protocol's RSA OAEP exchange, including the | ||
| protocol-defined SHA-1 OAEP and MGF1 digests and password/scramble XOR step. | ||
| Malformed ciphertext, malformed plaintext, and an incorrect password all | ||
| produce the normal `1045` / `28000` access-denied response. If no valid RSA key | ||
| pair is available, the same error code and SQLSTATE are returned with a message | ||
| that identifies the unavailable RSA key exchange and suggests TLS or key | ||
| configuration. |
This file contains hidden or 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 hidden or 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,57 @@ | ||
| #ifndef PROXYSQL_MYSQL_CACHING_SHA2_RSA_H | ||
| #define PROXYSQL_MYSQL_CACHING_SHA2_RSA_H | ||
|
|
||
| #include <memory> | ||
| #include <mutex> | ||
| #include <string> | ||
|
|
||
| #include <openssl/types.h> | ||
|
|
||
| struct CachingSha2RSAConfig { | ||
| bool auto_generate { true }; | ||
| std::string private_key_path; | ||
| std::string public_key_path; | ||
| std::string datadir; | ||
| }; | ||
|
|
||
| class CachingSha2RSAKeySnapshot { | ||
| public: | ||
| const std::string& public_key_pem() const { return public_key_pem_; } | ||
| size_t ciphertext_size() const { return ciphertext_size_; } | ||
|
|
||
| private: | ||
| friend class MySQL_Caching_Sha2_RSA; | ||
| std::shared_ptr<EVP_PKEY> private_key_; | ||
| std::string public_key_pem_; | ||
| std::string private_key_path_; | ||
| std::string public_key_path_; | ||
| size_t ciphertext_size_ { 0 }; | ||
| }; | ||
|
|
||
| struct CachingSha2RSAReloadResult { | ||
| bool accepted { false }; | ||
| bool changed { false }; | ||
| bool available { false }; | ||
| std::string error; | ||
| }; | ||
|
|
||
| class MySQL_Caching_Sha2_RSA { | ||
| public: | ||
| CachingSha2RSAReloadResult reload(const CachingSha2RSAConfig& config); | ||
| std::shared_ptr<const CachingSha2RSAKeySnapshot> acquire() const; | ||
| bool decrypt_password( | ||
| const std::shared_ptr<const CachingSha2RSAKeySnapshot>& snapshot, | ||
| const unsigned char* ciphertext, | ||
| size_t ciphertext_length, | ||
| const unsigned char* scramble, | ||
| size_t scramble_length, | ||
| std::string& password, | ||
| std::string* error = nullptr | ||
| ) const; | ||
|
|
||
| private: | ||
| mutable std::mutex mutex_; | ||
| std::shared_ptr<const CachingSha2RSAKeySnapshot> snapshot_; | ||
| }; | ||
|
|
||
| #endif | ||
This file contains hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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
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.
Uh oh!
There was an error while loading. Please reload this page.