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

Add SSL context for RedisCluster connections #85

Merged

Conversation

robin-brabants
Copy link
Contributor

@robin-brabants robin-brabants commented Mar 12, 2024

Q A
Documentation no
Bugfix no
BC Break no
New Feature yes
RFC no
QA no

Description

This small feature allows to pass an sslContext to the RedisCluster constructor from the phpredis extension.

Without this feature, one could not connect to a cluster using TLS. Now when specifying the correct protocol for the seed nodes (e.g.: 'seeds' => ['tls://nodeId-01.xxx:6379', 'tls://nodeId-02.xxx:6379']) and passing an sslContext one can connect to a cluster using TLS .

One can pass an empty array for the sslContext, but also explicitly specify non-default options for the TLS connection. For a full list of ssl context options see: https://www.php.net/manual/en/context.ssl.php.

This for example enables one to connect to an AWS elasticache redis cluster with in-transit encryption set to required due to security reasons.

@Ocramius
Copy link
Member

Ocramius commented Mar 12, 2024

TARGET THE develop BRANCH????

Is the template still foobar'd ?

Copy link
Member

@Ocramius Ocramius left a comment

Choose a reason for hiding this comment

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

I understand where this comes from, but the use case of verify_peer => false seems kinda anachronistic nowadays.

Possibly better to provision both host and client with a dummy certificate via https://github.com/FiloSottile/mkcert/blob/2a46726cebac0ff4e1f133d90b4e4c42f1edf44a/README.md ?

src/RedisClusterOptions.php Outdated Show resolved Hide resolved
@robin-brabants
Copy link
Contributor Author

TARGET THE develop BRANCH????

Is the template still foobar'd ?

The template mentions to make a PR for features against a development branch:

Pick the target branch based on the following criteria:

  • New feature, or refactor of existing code: develop branch

@robin-brabants
Copy link
Contributor Author

I understand where this comes from, but the use case of verify_peer => false seems kinda anachronistic nowadays.

Possibly better to provision both host and client with a dummy certificate via https://github.com/FiloSottile/mkcert/blob/2a46726cebac0ff4e1f133d90b4e4c42f1edf44a/README.md ?

it is just an example for a unit test

@@ -8,7 +8,7 @@
"license": "BSD-3-Clause",
"require": {
"php": "~8.1.0 || ~8.2.0 || ~8.3.0",
"ext-redis": "^5.0.2 || ^6.0",
"ext-redis": "^5.3.2 || ^6.0",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Passing a ssl/tls context to the RedisCluster constructor from the phpredis extension is apparently only introduced in version 5.3.2: https://github.com/phpredis/phpredis/blob/develop/CHANGELOG.md
I noticed this due to the failing pipeline.
This would of course be a breaking change though.

Copy link
Member

Choose a reason for hiding this comment

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

I havent had this kind of change ever but I remember that I did modified some redis range in the past. IMO having a check during CD that all the required extension versions are fulfilled should be a good thing, so I do not have a problem with that change personally, but how is this kind of stuff handled in other OSS.
Do you have experience here @Ocramius?

@robin-brabants robin-brabants marked this pull request as ready for review March 12, 2024 16:14
@robin-brabants robin-brabants force-pushed the feature/redis-cluster-ssl-context branch 3 times, most recently from 8e32c6b to 97961bd Compare March 13, 2024 15:37
@robin-brabants
Copy link
Contributor Author

I added a few commits which should fix the failing integration tests. Could they be ran again?

psalm.xml Outdated Show resolved Hide resolved
Copy link
Member

@boesing boesing left a comment

Choose a reason for hiding this comment

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

I'd added some comments, would be decent if we can improve this a little bit.
Sorry for the late response, I am not doing too much OSS at the moment.

@boesing
Copy link
Member

boesing commented Mar 22, 2024

I wonder if we can add an integration test where we actually setup a redis cluster with SSL and self-signed certificate to verify if this is actually working. I don't expect this in this PR tho as I think it would already suffice and I can understand that taking time to implement this kind of setup would be too much.
It took me quite some time to even have redis cluster docker setup up and running, since the docker image we are using here does not support SSL right now, we would have to create an own docker image. Thus I think I will create an issue off this comment once we merged this PR.

@robin-brabants robin-brabants force-pushed the feature/redis-cluster-ssl-context branch from c8db434 to 436e29e Compare March 26, 2024 14:41
@robin-brabants
Copy link
Contributor Author

Implemented an sslContext class right now which contains the sslcontext options in the fields.

I omitted the 'capture_peer_cert' and 'capture_peer_cert_chain' options since they are not relevant for us in my opinion.

I wanted to make some of the default values clearly visible in the constructor. I made them correspond to the actual sslContext default options at least for more recent php versions with the exception of 'SNI_enabled' which would make sense in my opinion to enable by default if possible.

@robin-brabants
Copy link
Contributor Author

@Ocramius @boesing
Are there still any changes required for this PR

@boesing
Copy link
Member

boesing commented Apr 10, 2024

Sorry, havent reviewed yet. Will probably do so either today or tomorrow evening.

Signed-off-by: robin-brabants <robin.brabants@tngtech.com>
Co-authored-by: robin-brabants <robin.brabants@tngtech.com>
Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com>
boesing and others added 7 commits April 10, 2024 22:48
…sl/tls context parameter was introduced in version 5.3.2

Signed-off-by: robin-brabants <robin.brabants@tngtech.com>
Co-authored-by: robin-brabants <robin.brabants@tngtech.com>
Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com>
Signed-off-by: robin-brabants <robin.brabants@tngtech.com>
Co-authored-by: robin-brabants <robin.brabants@tngtech.com>
Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com>
… TLS connection is attempted by default

Signed-off-by: robin-brabants <robin.brabants@tngtech.com>
Co-authored-by: robin-brabants <robin.brabants@tngtech.com>
Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com>
… phpredis RedisCluster class

Signed-off-by: robin-brabants <robin.brabants@tngtech.com>
Co-authored-by: robin-brabants <robin.brabants@tngtech.com>
Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com>
…ntext to the RedisCluster

Signed-off-by: robin-brabants <robin.brabants@tngtech.com>
Co-authored-by: robin-brabants <robin.brabants@tngtech.com>
Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com>
…tor to the code

Signed-off-by: robin-brabants <robin.brabants@tngtech.com>
Co-authored-by: robin-brabants <robin.brabants@tngtech.com>
Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com>
This refactors some of the `SslContext` implementation to have better readability, less complexity (regarding camel case handling, etc.) and explicit context serialization.

Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com>
@boesing boesing force-pushed the feature/redis-cluster-ssl-context branch from 135268e to d387d42 Compare April 10, 2024 20:49
@boesing
Copy link
Member

boesing commented Apr 10, 2024

I refactored the code a little bit, especially since I am not a fan from those abbreviations all round tech.
I renamed some properties but still preserve the context notation when converting the object to the ssl context array.

I'd say we should only allow 1:1 array notations which would be accepted by PHP as well, thats why I removed all that camel case handling and just have two dedicated methods, a named factory to instantiate our object from an SSL context array (in the notation supported by PHP) and a method which converts the object back to a PHP supported SSL context array.

I also do not allow RedisClusterOptions#setSslContext to consume an array. IMHO if that is being called from somewhere, it should be either null or the SslContext object.
I did override AdapterOptions#setFromArray to ensure that ssl_context or sslContext array keys are always converted to an object in case an array is passed.
So test is still passing.

I also removed all the ssl context defaults. That prevents us from having issues with several PHP versions where (whyever) defaults might change and then we have to see how to provide defaults for both versions. I do not really see that we should do that and thus I'd say lets allow passing null for any option and in case it is not explicitly set (i.e. null), we do not pass that in the array we pass to RedisCluster#__construct.

I also would say we should not require ext-openssl since it would be only required from upstream projects as this component does pretty much work without that extension (as I removed all the defaults which were using OPENSSL_* constants) and thus I'd say, that is a requirement which should be added by projects rather than this library.


I'd love to get some review of my changes and some feedback. If that works for you and you still see the feature is serving your needs, I'd love to get a quick 👍🏼 so that we can proceed.
Since I do not have a cluster serving via TLS, I am unable to verify if everything is working. I've created #88 to keep track that we should have integration tests up and running so that we do not accidentally break stuff.

But I'd be fine with releasing this without actual integration tests as its a new feature which needs to be explicitly implemented by projects and thus its okayish to depend on projects having integration testings up and running until we implement #88.

Thanks for your massive work here and I'm happy to see your feedback.


Had to rebase with latest 2.8.x as renovate updated composer.lock...

@robin-brabants
Copy link
Contributor Author

Sorry that I only see your improvement right now, but was a bit preoccupied.
I would have some time again after the weekend and will give my feedback on Monday.

src/SslContext.php Show resolved Hide resolved
test/unit/SslContextTest.php Show resolved Hide resolved
@robin-brabants
Copy link
Contributor Author

@boesing
Your changes look great to me! I just had two minor comments.
For me it is fine to merge this PR as is.

@boesing boesing self-assigned this Apr 16, 2024
@boesing boesing changed the title support passing ssl context for RedisCluster Add SSL context for RedisCluster connections Apr 16, 2024
@boesing boesing merged commit 82c636c into laminas:2.8.x Apr 16, 2024
15 checks passed
@boesing boesing added this to the 2.8.0 milestone Apr 16, 2024
@boesing
Copy link
Member

boesing commented Apr 16, 2024

Thanks @robin-brabants!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants