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

Support for setting CURLSSLOPT_NATIVE_CA on Windows #2733

Closed
1 of 2 tasks
pr0g opened this issue Nov 3, 2023 · 5 comments
Closed
1 of 2 tasks

Support for setting CURLSSLOPT_NATIVE_CA on Windows #2733

pr0g opened this issue Nov 3, 2023 · 5 comments
Labels
closing-soon This issue will automatically close in 4 days unless further comments are made. guidance Question that needs advice or information.

Comments

@pr0g
Copy link
Contributor

pr0g commented Nov 3, 2023

Describe the feature

(moved from discussion #2724)

Pass CURLSSLOPT_NATIVE_CA to aws-sdk-cpp

Use Case

This might be an issue but it's also very likely this is possible and I just don't know how to do it.

I am using aws-sdk-cpp on Windows and have a custom build of OpenSSL and Curl. When I try to make an https request using Curl directly, I get the error:

 SSL peer certificate or SSH remote key was not OK

I can fix this by either setting a certificate with:

curl_easy_setopt(curl, CURLOPT_CAINFO, "cacert.pem");

(Where "cacert.pem" is one I grabbed from here).

Or I can use:

curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NATIVE_CA);

Where CURLSSLOPT_NATIVE_CA states "Tell libcurl to use the operating system's native CA store for certificate verification" (see here for more info).

The problem with this option is I don't see a way to pass that through to AWS SDK. I can get things to work if I use:

Aws::Client::ClientConfiguration client_config;
client_config.region = "<my-region>";
client_config.caFile = "cacert.pem";

But it would be nice if I could just use the operating system's native CA store.

Is there a way to do this that I'm not seeing? I initialize Curl outside of aws-sdk-cpp and I've tried setting the property right after curl_global_init(CURL_GLOBAL_ALL);.

Something like...

curl_global_init(CURL_GLOBAL_ALL);

if (CURL* curl = curl_easy_init()) {
  curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NATIVE_CA);
}

Aws::SDKOptions options;
options.httpOptions.initAndCleanupCurl = false;
Aws::InitAPI(options);

...

Aws::ShutdownAPI(options);
curl_global_cleanup();

But that unfortunately does not seem to work. If there's a way to do this I'd be really curious to know. Thank you!

Proposed Solution

Pass Curl option to aws-sdk-cpp at initialization time to use the operating system's native CA store.

Other Information

No response

Acknowledgements

  • I may be able to implement this feature request
  • This feature might incur a breaking change
@pr0g pr0g added feature-request A feature should be added or improved. needs-triage This issue or PR still needs to be triaged. labels Nov 3, 2023
@SergeyRyabinin
Copy link
Contributor

Hi @pr0g ,

There is a an abstract method on the Curl HTTP Client wrapper:

virtual void OverrideOptionsOnConnectionHandle(CURL*) const {}

You should be able to inherit the built-in Curl HTTP Client and then provide your implementation in this method. Please also refer to "Override the default HTTP client factory" in our documentation in order to make SDK to use your new customized client.

Best regards,
Sergey

@pr0g
Copy link
Contributor Author

pr0g commented Nov 8, 2023

Hi @SergeyRyabinin,

Thank you very much for getting back to me about this. This sounds like exactly what I was after! 🥳 Apologies I didn't spot this before.

I'll test this out soon and report back with how it went.

Thanks again very much for your help!

@jmklix jmklix added closing-soon This issue will automatically close in 4 days unless further comments are made. guidance Question that needs advice or information. and removed needs-triage This issue or PR still needs to be triaged. feature-request A feature should be added or improved. labels Nov 8, 2023
@pr0g
Copy link
Contributor Author

pr0g commented Nov 11, 2023

Closing for now, will reopen if needed, thanks again 👍

@pr0g pr0g closed this as completed Nov 11, 2023
Copy link

⚠️COMMENT VISIBILITY WARNING⚠️

Comments on closed issues are hard for our team to see.
If you need more assistance, please either tag a team member or open a new issue that references this one.
If you wish to keep having a conversation with other community members under this issue feel free to do so.

@pr0g
Copy link
Contributor Author

pr0g commented Nov 19, 2023

Just for completeness in case anyone else stumbles across this trying to do the same thing, this is what I used:

class CustomCurlHttpClient : public Aws::Http::CurlHttpClient
{
public:
  CustomCurlHttpClient(const Aws::Client::ClientConfiguration& client_config)
    : Aws::Http::CurlHttpClient(client_config) {}
private:
  void OverrideOptionsOnConnectionHandle(CURL* curl) const override {
    curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NATIVE_CA);
  }
};

class CustomHttpClientFactory : public Aws::Http::HttpClientFactory
{
public:
  std::shared_ptr<Aws::Http::HttpClient> CreateHttpClient(
    const Aws::Client::ClientConfiguration& client_configuration) const override {
    return std::make_shared<CustomCurlHttpClient>(client_configuration);
  }
  virtual std::shared_ptr<Aws::Http::HttpRequest> CreateHttpRequest(
    const Aws::String& uri, Aws::Http::HttpMethod method,
    const Aws::IOStreamFactory& streamFactory) const override {
    return CreateHttpRequest(Aws::Http::URI(uri), method, streamFactory);
  }
  virtual std::shared_ptr<Aws::Http::HttpRequest> CreateHttpRequest(
    const Aws::Http::URI& uri, Aws::Http::HttpMethod method,
    const Aws::IOStreamFactory& streamFactory) const override {
    auto request =
      std::make_shared<Aws::Http::Standard::StandardHttpRequest>(uri, method);
    request->SetResponseStreamFactory(streamFactory);
    return request;
  }
};

...

// init time
Aws::SDKOptions options;
options.httpOptions.initAndCleanupCurl = false; // I call curl_global_init/curl_global_cleanup
options.httpOptions.httpClientFactory_create_fn = []() {
  return std::make_shared<CustomHttpClientFactory>();
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closing-soon This issue will automatically close in 4 days unless further comments are made. guidance Question that needs advice or information.
Projects
None yet
Development

No branches or pull requests

3 participants