Skip to content

[4.0] Add TLS transfer encryption for database connections at installation#26888

Closed
richard67 wants to merge 48 commits intojoomla:4.0-devfrom
richard67:4.0-dev-tls-encrypt-db-connections-at-install
Closed

[4.0] Add TLS transfer encryption for database connections at installation#26888
richard67 wants to merge 48 commits intojoomla:4.0-devfrom
richard67:4.0-dev-tls-encrypt-db-connections-at-install

Conversation

@richard67
Copy link
Copy Markdown
Member

@richard67 richard67 commented Nov 1, 2019

Pull Request for Issue # .

Follow-up to PR #26375 and PR #26889.

Summary of Changes

This Pull Request (PR) adds the possibility to use an encrypted database connection like it was added with PR #26375 to the CMS already during the installation.

After PR #26375 , again a big thank you to @andrepereiradasilva for the implementation of this new feature.

The installation form is extended by new fields for the encryption parameters in the same way as the server section of the Global Configuration form was extended with PR #26375 and later modified with PR #26889. It also includeas already the changes proposed with PR #27320 for Global Configuration.

Database related parts of the installation are extended for using encrypted connection in the same way as the installed CMS later can do after PR #27320 has been merged.

Testing Instructions

Please wait with testing. I will make some changes in the next day or make a new PR.

Pre-conditions

Have a database server which supports encrypted connections.

If you have a standard installation of MySQL 5.7 or later or comparable MariaDB server, or a PostgreSQL 10 or later, the database server comes with a self signed server certificate and enabled encryption support, so one-way (i.e. server side) authentication without certificate verification works out of the box.

For a webspaces with databases provided by a hosting provider it may be different, especially with shared hosting. But on my shared hosting space one-way authentication without certificate verification works, too.

For certificate verification it is required that the common name (CN) in the server certificate is equal to the server name used by the DB client. This is not the case with the default certificates used by the standard database setup mentioned above.

Some links to documentation of connection encryption for the particular kinds of databases:

But for testing this PR it is enough to have one-way encryption without certificate verification working.

Instructions

  1. Start a new installation of a 4.0-dev branch plus changes of this PR applied, i.e. either apply it with some git tool on a clean 4.0-dev branch, or apply it on an existing 4.0-dev installation e.g. with patchtester and the remove configuration.php and deleted database tables.

  2. When coming to the form with database information, enter "localhost" as database server.
    Result: No database connection encryption options are shown, see section "Expected result" screenshot 1.

  3. Change the server to something else than "localhost".
    Result: Database connection encryption options are shown. The default option for the encryption method is selected, no other fields are shown. See section "Expected result" screenshot 2.

  4. Change some of the options and then change server back to "localhost", then again change it back to something else.
    Result: The previously entered/selected options acre cleared/reset to default.

  5. Select the 2nd option "One-way authentication" of field "Connection Encryption" and check which fields are shown for encryption parameters.
    Result: An additonal boolean field is shown to switch on or off verification of the server certificate, see section "Expected result" screenshot 3.

  6. Switch on server certificate verification and change database type if necessary to MySQLi.
    Result: 2 additional fields "Path to CA File" and "Path to CA Folder" are shown, see section "Expected result" screenshot 4.

  7. Change database type to MySQL(PDO).
    Result: No change.

  8. Change database type to PostgreSQL (PDO).
    Result: Only the additional field "Path to CA File" is shown, see section "Expected result" screenshot 5.

  9. Change database back to MySQLi, select the 3nd option "Two-way authentication" of field "Connection Encryption" and switch off server certificate verification.
    Result: 3 additional fields "Path to Private Key File", "Path to Certificate File" and "Supported Cipher Suite" are shown, see section "Expected result" screenshot 6.

  10. Switch on server certificate verification.
    Result: 2 additional fields "Path to CA File" and "Path to CA Folder" are shown, see section "Expected result" screenshot 7.

  11. Change database type to MySQL(PDO).
    Result: No change.

  12. Change database type to PostgreSQL (PDO) and switch off server certificate verification.
    Result: Fields "Path to CA File", "Path to CA Folder" and "Supported Cipher Suite" disappear, see section "Expected result" screenshot 8.

  13. Switch on server certificate verification.
    Result: 1 field "Path to CA File" is shown, see section "Expected result" screenshot 9.

  14. Change the server to the full host name (i.e. including domain suffix of the particular network, if some) of your database server and select the right database type.
    The adjust some connection encryptions parameters in a way which should not work, e.g. select 2-way authentication without entering the values in the other fields.
    Then continue to the next step of the installation.
    Result: The installation can't continue, it shows an error on database connection, see ection "Expected result" screenshot 10.

  15. Now change encryption parameters to something which should work, e.g. one-way authentication without server certificate verification, which should work out of the box in most cases.
    Then continue to the next step of the installation.
    Result: Installation finish with success.

  16. Check the database connection encryption parameters in backend in the server tab of Global Configuration.
    Result: The parameters still have the same values as selected/entered during installation, see section "Expected result" screenshot 11.

  17. Verify in System Information that database connection encryption is on and working, see section "Expected result" screenshot 11.

Expected result

  1. No encryption if database server is 'localhost':

j4-installation-dbconfig-localhost

  1. Default encryption:

j4-installation-dbconfig-ssl-default

  1. One-way (= server) authentication without server certificate verification:

j4-installation-dbconfig-ssl-one-way

  1. One-way (= server) authentication with server certificate verification, MySQLi and MySQL (PDO):

j4-installation-dbconfig-ssl-one-way_2

  1. One-way (= server) authentication with server certificate verification, PostgreSQL (PDO):

j4-installation-dbconfig-ssl-one-way_3

  1. Two-way (= server and client) authentication without server certificate verification:

j4-installation-dbconfig-ssl-two-way-mysql

  1. Two-way (= server and client) authentication with server certificate verification, MySQLi and MySQL (PDO):

j4-installation-dbconfig-ssl-two-way-mysql_2

  1. Two-way (= server and client) authentication without server certificate verification, PostgreSQL (PDO):

j4-installation-dbconfig-ssl-two-way-postgresql

  1. Two-way (= server and client) authentication with server certificate verification, PostgreSQL (PDO):

j4-installation-dbconfig-ssl-two-way-postgresql_2

  1. DB connection fails with invalid values for encryptions parameters:

j4-installation-dbconfig-ssl-bad-values

  1. With valid encryption parameters installation finishs with success.
    After that, the server tab of Global Configuration shows the parameters as entered/selected during installation, e.g. here for one-way encryption without certificate verification, which should work out of the box with actual databases.

j4-installation-dbconfig-ssl-good-end

The System Information shows that database connection encryption is on, e.g. for the example mentioned before:

snap-10

Actual result

No encryption options in database configuration section of the installation form.

Documentation Changes Required

Same as PR #26375 : New feature has to be documented. At least installation documentation has to be extended for this PR here. For PR #26375 it would need to extend documentation of the server section of Global Configuration, the Privacy Dashboard Module and the System Information view.

@joomla-cms-bot joomla-cms-bot added Language Change This is for Translators PR-4.0-dev labels Nov 1, 2019
@richard67 richard67 changed the title [4.0] [New feature] [WiP] Add tls transfer encryption for database connections at installation [4.0] [WiP] Add tls transfer encryption for database connections at installation Nov 1, 2019
@richard67
Copy link
Copy Markdown
Member Author

richard67 commented Nov 1, 2019

Potential testers please wait with testing until title does not contain "[WiP]" anymore and status on GitHub is not draft anymore.

@richard67 richard67 changed the title [4.0] [WiP] Add tls transfer encryption for database connections at installation [4.0] Add tls transfer encryption for database connections at installation Nov 1, 2019
@richard67 richard67 marked this pull request as ready for review November 1, 2019 17:58
@richard67
Copy link
Copy Markdown
Member Author

PR is ready for test now.

@richard67 richard67 changed the title [4.0] Add tls transfer encryption for database connections at installation [4.0] Add TLS transfer encryption for database connections at installation Nov 1, 2019
@brianteeman
Copy link
Copy Markdown
Contributor

I still don't understand how @HLeithner was able to do a successful test

@richard67
Copy link
Copy Markdown
Member Author

Server certificate verification and 2-way is a bit tricky because of the requirements of the db servers and clients regarding ownership and file system permissions for the key files, and in case of Linux with AppArmous also regarding the location of the key and certificate files on the server. But I have tested all with MySQL and PostgreSQL using separate servers for Joomla (= db client) and the db server, and I was able to make all work, 1-way and 2-way with and without server cert verification. I assume he has done it in the same way, at least that was what he ewas discussing with me on Glip. So I assume he has made a real test.

But it seems we both haven't tested the scenario with 2-way without server cert verification and missing values for client cert and key files.

@brianteeman
Copy link
Copy Markdown
Contributor

Its an important part of all testing to see what happens when things don't work as well as when they do ;)

@richard67
Copy link
Copy Markdown
Member Author

Sure. But nobody is perfect, or are you?

@brianteeman
Copy link
Copy Markdown
Contributor

you misunderstood the meaning of my sentence

@richard67
Copy link
Copy Markdown
Member Author

Anyway thanks for the findings ... I have to think and investigate how to fix it ... maybe there is not really a way to find out if finally 1 or 2 way is used ... stay tuned.

@richard67
Copy link
Copy Markdown
Member Author

@andrepereiradasilva Since you had the original idea and implemented the feautre in the framework db package: Do you have an idea how to solve the issues found by @brianteeman above? If so, all suggestions are welcome.

@richard67
Copy link
Copy Markdown
Member Author

richard67 commented Dec 20, 2019

@brianteeman For the UI issue "hidden feature if localhost" it could maybe help to show a field or a message when localhost is chosen, telling that localhost will mean what a socket connection is used for which encryption is not possible, and so the encryption related options are not shown, and that this is safe when the local host is safe and that it has performance advantages, but if someone explicitely wants to encrypt also a connection to localhost he/she could use 127.0.0.1 or ::1 to enforce a TCP connection. This would make the feature not be hidden anymore when localhost is chosen. What do you think? And do you think it is possible to tell that in an as short as possible sentence? If so, suggestions are welcome. And what is better: A field (if yes of which type, label or text) with a showon in case of localhost, or a message alert?

The other issues with 1-way and 2-way I have to think about still how to solve that.

@brianteeman
Copy link
Copy Markdown
Contributor

Sorry but that idea doesnt make things any clearer to me

@richard67
Copy link
Copy Markdown
Member Author

@brianteeman As far as I understood one of the issues is that nothing is shown about availability of connection encryption if one has chosen localhost. My idea was to show some hint in that case so one can see there is such feature, and to explain a bit that it is not unsafe or a problem when not using it for localhost. The question was how or where to show that information in the best way.

@HLeithner
Copy link
Copy Markdown
Member

For the 2-way authentication we can only check if the private key exists, but the server have to enforce the 2-way (client side authentication). That's what I have tested.

You have to required a certificate from the client in the mysql config to let 2-way fail.

And yes you are right we should check if a private key file exists when 2-way is selected, on the code site the database driver doesn't care it is happy if it connects.

About the ui topic, maybe it's better so always show the TLS button and prevent the user from entering localhost (auto convert to 127.0.0.1) if he/she activates it.

@brianteeman
Copy link
Copy Markdown
Contributor

brianteeman commented Dec 21, 2019

For the 2-way authentication we can only check if the private key exists, but the server have to enforce the 2-way (client side authentication). That's what I have tested.

But were you connected as 1 way or 2 way

You have to required a certificate from the client in the mysql config to let 2-way fail.

and thats not something we can test for ?

And yes you are right we should check if a private key file exists when 2-way is selected, on the code site the database driver doesn't care it is happy if it connects.

but only as 1 way?

So should the "verify certificate" option always be checked? Sorry not had time to check if that is a verify client or verify server check.

About the ui topic, maybe it's better so always show the TLS button and prevent the user from entering localhost (auto convert to 127.0.0.1) if he/she activates it.

I agree to always show the tls button - not sure about autoconverting the localhost. maybe that should be just part of the validation test.

@richard67
Copy link
Copy Markdown
Member Author

@brianteeman

So should the "verify certificate" option always be checked?

No, it should not always be checked because e.g. on my shared hosting (1&1) 1-way authentication works, but not with certificate verification because I don't have any access to the CA certificate.

Sorry not had time to check if that is a verify client or verify server check.

It's a check if the CA of the server certificate fits to the CA certificate . On MySQL the verification can be done with or without an additional check if the host name used for the database connection is equal to the common name (CN) in the server certificate. It could be good switch off the server name check because the certificates coming with a standard installation of MySQL or PostgreSQL have something else than the hostname as CN. But as far as I know up to now, on PostgreSQL the server name and CN are always compared, so currently there is no toggle button to switch that off. Maybe it could make sense to add such button? But this would be one more field being shown only for MySQLi and MySQL (PODO), and it maybe would make things more complicated. Your opinion on this point is welcome. Meanwhile I will check again deeper if PostgreSQL allows to switch off server name check so we could use such new button for all databases.

@brianteeman and @HLeithner Thanks a lot for feedback and findings and ideas.

Maybe it would be easier if I implement changes in my PR #27320 for Global Config, i.e. after installation, or maybe make new draft PRs for that to test some UI changes, and then if that is ok make a new PR for the installation to replace this one here. What do you think? Would this make testing easier? Or shall we continue in this PR here to have all discussions at one place? Please share your opinion.

@richard67
Copy link
Copy Markdown
Member Author

And yes you are right we should check if a private key file exists when 2-way is selected, on the code site the database driver doesn't care it is happy if it connects.

I will work on implementing the checks if the files (client private key file and client certificate file and in case of certificate verification on also the CA file or folder, if specified) exist. But any help is welcome, e.g. advise if we shall limit the files location to folders below the Joomla root or not. But maybe such things can be easily added later.

About the ui topic, maybe it's better so always show the TLS button and prevent the user from entering localhost (auto convert to 127.0.0.1) if he/she activates it.

Maybe we could clear the "Host" field and show an alert when someone changes from "Default" to "One-way" or "Two-way"? The alert could tell in brief words that encryption will not work with localhost because of socket connection and that 127.0.01 or ::1 (depending on IP version) can be used instead to enforce a TCP connection?

We should not automatically set it to 127.0.0.1 because this will not work on a pure IP v6 system (ok, very unlikely case but theoretically possible).

@brianteeman
Copy link
Copy Markdown
Contributor

Sorry I can't really help as I'm now away until the new year at a conference with limited time and internet access

@richard67
Copy link
Copy Markdown
Member Author

Sorry I can't really help as I'm now away until the new year at a conference with limited time and internet access

@brianteeman No problem, thanks so far, have a merry x-mas and a happy new year and a good conference, and maybe the works on that database connection encryption stuff will take a while so you can continue to help and advise next year.

@richard67
Copy link
Copy Markdown
Member Author

@HLeithner Regarding check if files or folders exist: We currently have that nowhere in Global Config, neither for log folder nor temp folder nor cache folder or whatever folders and files can be specified there. Not sure if it would be good to have that at one place (db encryption) but nowhere else, and not sure if there are maybe security reasons why we don't check these. And it seems there are no ready validation rules for that. What do you think?

@HLeithner
Copy link
Copy Markdown
Member

For the 2-way authentication we can only check if the private key exists, but the server have to enforce the 2-way (client side authentication). That's what I have tested.

But were you connected as 1 way or 2 way

Connected 2-way and checked for fail if private key was not supplied

You have to required a certificate from the client in the mysql config to let 2-way fail.

and thats not something we can test for ?

Can't think of, It's a flag in the creation of the database user.

GRANT ALL PRIVILEGES ON joomla.* to 'joomlal'@'%' IDENTIFIED BY '<joomla-password>'
  REQUIRE SUBJECT '/C=AT/ST=Vienna/L=Vienna/O=ITronic/OU=Production/CN=joomla-website';

This would require a certificate on login with an exact subject. But it's also possible just require a certificate with the same CA as the server

GRANT ALL PRIVILEGES ON joomla.* to 'joomla'@'%' IDENTIFIED BY '<joomla-password>' REQUIRE X509;

And yes you are right we should check if a private key file exists when 2-way is selected, on the code site the database driver doesn't care it is happy if it connects.

but only as 1 way?

I'm not sure if the server simple ignores the certificate or not. I would expect that it's just ignored but should be tested.

So should the "verify certificate" option always be checked? Sorry not had time to check if that is a verify client or verify server check.

That's the exact point, it's both, 1-way is "Verify Server" and 2-way is "Verify Server and verify Client", but you can't do only "Verify Client".

About the ui topic, maybe it's better so always show the TLS button and prevent the user from entering localhost (auto convert to 127.0.0.1) if he/she activates it.

I agree to always show the tls button - not sure about autoconverting the localhost. maybe that should be just part of the validation test.

Warning message that it's not possible to use TLS over UDS (which is automatically tried if using "localhost" as name)...

In this case I'm not sure if "Verify Client" is possible at all...

(That's all about MySQL, Pgsql should be similar but I don't know if the pgsql driver does the same magic for UDS with name "localhost")

@HLeithner
Copy link
Copy Markdown
Member

@HLeithner Regarding check if files or folders exist: We currently have that nowhere in Global Config, neither for log folder nor temp folder nor cache folder or whatever folders and files can be specified there. Not sure if it would be good to have that at one place (db encryption) but nowhere else, and not sure if there are maybe security reasons why we don't check these. And it seems there are no ready validation rules for that. What do you think?

I'm not sure if we really need directory and file for certificate. Automatically decide if "path" is a file or dir should do the same with less confusion...

@richard67
Copy link
Copy Markdown
Member Author

Automatically decide if "path" is a file or dir should do the same with less confusion...
@HLeithner So or so we don't have any check yet in Global Configuration for existance for other folders or files we specify.

@brianteeman
Copy link
Copy Markdown
Contributor

Will that path even be in a space that the web user can access?

@richard67
Copy link
Copy Markdown
Member Author

richard67 commented Dec 21, 2019

Will that path even be in a space that the web user can access?

@brianteeman Yes. If you mean the user of Joomla via browser: No, the file or folder is located on the Joomla web server which is equal to the db client. It is not accesible from the web client = the user's PC.

@richard67
Copy link
Copy Markdown
Member Author

richard67 commented Dec 22, 2019

@HLeithner If the connections fails or not for particular options can be determined by the client using the ssl-mode variable on MySQL (not sure yet if MariaDB supports that, too) or sslmode on PostgreSQL. As far as I could see up to now, only the PostgreSQL (PDO) driver uses this possibility. So I think that's why currently on MySQL things depend on server settings.

The ssl-mode/sslmode variable allows to specify if the host name of the server shall be checked in the server's certificate, too (verify CA), or if not (verify full). For this we don't have an option yet, but it could be useful to control that, too, because the certificates generated by MySQL and PostgreSQL for a standard installation use common names (CN) different to the host name.

See here for a description of the MySQL SSL modes: https://dev.mysql.com/doc/refman/8.0/en/using-encrypted-connections.html, just scroll down to section "Client-Side Configuration for Encrypted Connections".

See here for a description of the PostgreSQL SSL modes: https://ankane.org/postgres-sslmode-explained.

So maybe it could make sense to enhance some of the DB drivers to set that variable in the right way so the 1-way or 2-way value in Global Configuration (or here in the installation form) really controls the behavior when connecting.

Am still investigating.

Update: It seems that MariaDB does not support ssl-mode.

@richard67
Copy link
Copy Markdown
Member Author

I think I've found a way to solve the issues. Say tuned and wait with testing until I report back here that it is ready. Maybe I will make a new PR to replace this one, maybe I'll modify this one, not sure yet.

@richard67
Copy link
Copy Markdown
Member Author

Closing in favour of #27348 .

@richard67 richard67 closed this Dec 25, 2019
@richard67 richard67 deleted the 4.0-dev-tls-encrypt-db-connections-at-install branch December 27, 2019 14:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Language Change This is for Translators

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants