Skip to content

Conversation

@olivierbellone
Copy link
Contributor

r? @brandur
cc @stripe/api-libraries @remistr

This PR aims to solve the various TLS issues that some of our users have encountered, usually caused by weird interactions between software versions (most notably curl and its underlying SSL library, typically but not always OpenSSL) and the way we configure TLS in the library.

To summarize:

  • the library does not set CURLOPT_SSLVERSION at all anymore. From the PHP docs: "Your best bet is to not set this and let it use the default. "
  • users who need to set this option (on some older RedHat / CentOS versions, the server is capable of using TLS 1.2 but will use TLS 1.0 unless CURLOPT_SSLVERSION is explicitly set to either CURL_SSLVERSION_TLSv1 or CURL_SSLVERSION_TLSv1_2) can now do so by passing the option themselves (see README)
  • curl constants definitions have been moved out of the request() method so that we don't check if the constants are already defined for every request
  • the X-Stripe-Client-User-Agent header now includes curl version and the SSL library name and version

This update will unfortunately break some users' integrations (for those cases where the library happens to work now, but will require manually setting CURLOPT_SSLVERSION after the update), and so should be released with a major version bump.

Copy link
Contributor

@brandur brandur left a comment

Choose a reason for hiding this comment

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

This looks great to me; thanks again @olivierbellone! If it's peaceful with Field Engineering, I'll cut a major release with this later today like we talked about.

if (!defined('CURL_SSLVERSION_TLSv1_2')) {
define('CURL_SSLVERSION_TLSv1_2', 6);
}
// @codingStandardsIgnoreEnd
Copy link
Contributor

Choose a reason for hiding this comment

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

In retrospect, this definitely fits best up in the header of this file. Nice!

$curl = new \Stripe\HttpClient\CurlClient(array(CURLOPT_SSLVERSION => CURL_SSLVERSION_TLSv1));
\Stripe\ApiRequestor::setHttpClient($curl);
```

Copy link
Contributor

Choose a reason for hiding this comment

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

Minor comment but I'd recommend that you add the exact error message people might get on this page. This is helpful for someone looking for the exact error either on the page or via Google.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Great point. Done!


// @codingStandardsIgnoreStart
// PSR2 requires all constants be upper case. Sadly, the CURL_SSLVERSION
// constants to not abide by those rules.
Copy link
Contributor

Choose a reason for hiding this comment

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

minor nit "constants to not" => "constants do not"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.


$langVersion = phpversion();
$uname = php_uname();
$curlVersion = curl_version();
Copy link
Contributor

Choose a reason for hiding this comment

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

have we confirmed that calling this has a minimal impact? We've discussed this before in private but can't remember seeing clear results

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 ran some basic benchmarking, and it takes approximately 1.3 seconds to run 1 million calls to curl_version on my laptop. Given that ~all of our users will never send more than 100 req/s, I think we're fine.

@remi-stripe
Copy link
Contributor

Added a few minor comments here to address first but otherwise I think we're ready to ship. Since this is a major change, it might be worth delaying it a bit more and trying to think of anything we've wanted to change or fix for some time but couldn't because it would require a major version release

@pderksen
Copy link
Contributor

Not sure if this helps or is too late...

Though they don't use this Stripe PHP library, the WooCommerce Stripe payment gateway added this:
woocommerce/woocommerce-gateway-stripe@877dcab

@remi-stripe
Copy link
Contributor

@pderksen this is the original code we had in our library too as far as I can tell (they even mention olivier's name directly in the comments).

Unfortunately, we've ended up in situations where some users have PHP built with one specific version of curl and then uses a completely different one in production. When that happens, forcing the constant sometimes doesn't work at all producing errors such as the one documented in #289.

This PR is a different attempt to avoid this issue. We now rely on curl doing the right thing by default and then provide an option for users to explicitly force a different constant otherwise if they need to.

@brandur
Copy link
Contributor

brandur commented Sep 21, 2016

Since this is a major change, it might be worth delaying it a bit more and trying to think of anything we've wanted to change or fix for some time but couldn't because it would require a major version release

@remistr Given that major version releases tend to be slightly intimidating as is, what do you think about trying to keep this one fairly minimal? I'm a little worried that if there are too many other changes they might present a bit of a barrier to upgrade.

@remi-stripe
Copy link
Contributor

@brandur well that seems the opposite of what a major release should be no? Otherwise we'll keep not changing things we want to fix because it's too minor for a major release and at the same time have to release major releases every time something less minor changes.

I can't remember a specific thing we wanted to fix but couldn't recently. I'm just trying to advocate for taking this a bit slower than usual and trying to make sure we're not missing a quick win we could get and avoid a 5.X in a few weeks.

@olivierbellone
Copy link
Contributor Author

Hey @pderksen, thanks. As @remistr pointed out, this is how we previously set the option in our own library, and I'm the one who suggested that they do the same here. I've left another comment to let them know about our latest findings and this new update.

@brandur
Copy link
Contributor

brandur commented Sep 22, 2016

I can't remember a specific thing we wanted to fix but couldn't recently. I'm just trying to advocate for taking this a bit slower than usual and trying to make sure we're not missing a quick win we could get and avoid a 5.X in a few weeks.

Well I should point out that we're not burning through major releases at an incredible rate (the last was almost a year and a half ago), so it doesn't seem like we'd be starting a 5.x line anytime soon. But cool, it would be nice to get some of the people on #289 fixed up, but aside from that I guess we're not in a particular rush. Let me know when you think it would be wise to move forward on this one.

@remi-stripe
Copy link
Contributor

@brandur Then I think we're okay merging and releasing this!

@olivierbellone
Copy link
Contributor Author

I added a paragraph at the end of the README for plugin devs, to let them know about setAppInfo (this should have been in #294) and that they should plan for a configuration option to set CURLOPT_SSLVERSION if they want to ensure that their plugin can be used on all systems.

Feel free to tweak the wording or just rewrite the whole thing!

Copy link
Contributor

@brandur brandur left a comment

Choose a reason for hiding this comment

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

+1 to trying out the new README section. I left one minor comment on a typo above, but this looks good to me. Lets get it shipped out today.

README.md Outdated

Alternately, a callable can be passed to the CurlClient constructor that returns the above array based on request inputs. See `testDefaultOptions()` in `tests/CurlClientTest.php` for an example of this behavior. Note that the callable is called at the beginning of every API request, before the request is sent.

### SSL / TLS compatibiliy issues
Copy link
Contributor

Choose a reason for hiding this comment

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

Ugh, pretty minor, but I just noticed this typo on "compatibility". Mind fixing that?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done!

@olivierbellone
Copy link
Contributor Author

@brandur Sorry for the delay, GitHub failed to notify me for some reason. Typo is fixed, let's 🚢 this!

@brandur brandur merged commit 329af1d into master Sep 28, 2016
@brandur brandur deleted the ob-fix-289 branch September 28, 2016 17:43
@brandur
Copy link
Contributor

brandur commented Sep 28, 2016

Released as 4.0.0. Fingers crossed :)

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.

6 participants