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

[WIP] HTTP exporter support ssl credentials #938

Closed
wants to merge 1 commit into from

Conversation

pavanshahm
Copy link

@pavanshahm pavanshahm commented Aug 3, 2021

Fixes # (issue)

Changes

We needed to include ssl credentials if we wanted to use the http exporter so we added an additional option in http_exporter_options in order to allow it.

We also needed to update the curl.BUILD files in order to build cURL with the https protocol supported. This was done with a lot of trial and error and copied from the tensorflow build file, so I'm not sure which options are actually necessary and which ones are not.

Unit Tests are pending, but let me know if this is the right approach before I write those tests.

  • CHANGELOG.md updated for non-trivial changes
  • Unit tests have been added
  • Changes in public API reviewed

@pavanshahm pavanshahm requested a review from a team August 3, 2021 15:07
@linux-foundation-easycla
Copy link

CLA Not Signed

@codecov
Copy link

codecov bot commented Aug 3, 2021

Codecov Report

Merging #938 (45a438e) into main (d6c187c) will decrease coverage by 0.06%.
The diff coverage is 55.56%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #938      +/-   ##
==========================================
- Coverage   95.36%   95.30%   -0.05%     
==========================================
  Files         160      160              
  Lines        6779     6786       +7     
==========================================
+ Hits         6464     6467       +3     
- Misses        315      319       +4     
Impacted Files Coverage Δ
...nclude/opentelemetry/ext/http/client/http_client.h 93.34% <ø> (ø)
...ntelemetry/ext/http/client/curl/http_client_curl.h 89.63% <33.34%> (-1.72%) ⬇️
...lemetry/ext/http/client/curl/http_operation_curl.h 77.34% <66.67%> (-0.74%) ⬇️
...pi/include/opentelemetry/context/runtime_context.h 97.50% <0.00%> (+0.04%) ⬆️

@owent
Copy link
Member

owent commented Aug 4, 2021

I have thought using civetweb to setup a temporary HTTP server for unit test. Because prometheus-cpp also depend it. We can also use it without import another library or binary.
It maybe need more discussion about how to test HTTP requests. @maxgolov @lalitb

@lalitb
Copy link
Member

lalitb commented Aug 4, 2021

I have thought using civetweb to setup a temporary HTTP server for unit test. Because prometheus-cpp also depend it. We can also use it without import another library or binary.
It maybe need more discussion about how to test HTTP requests. @maxgolov @lalitb

@owent - This looks good - production-ready embeddable web-server, but just wondering whether we really need this for unit tests. What advantage do you think we will get from this over our internal http server specifically for unit-tests?

Copy link
Member

@owent owent left a comment

Choose a reason for hiding this comment

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

I have thought using civetweb to setup a temporary HTTP server for unit test. Because prometheus-cpp also depend it. We can also use it without import another library or binary.
It maybe need more discussion about how to test HTTP requests. @maxgolov @lalitb

@owent - This looks good - production-ready embeddable web-server, but just wondering whether we really need this for unit tests. What advantage do you think we will get from this over our internal http server specifically for unit-tests?

We need HTTPS here.If implementation SSL support for http server need a lot codes, maybe it's easier to use a third party library?

@@ -125,6 +125,8 @@ class Request

virtual void SetTimeoutMs(std::chrono::milliseconds timeout_ms) noexcept = 0;

virtual void IncludePermissionsFilePath(std::string filepath) noexcept = 0;
Copy link
Member

Choose a reason for hiding this comment

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

Maybe we should use nosdt::string_view instead of std::string here?

@@ -68,6 +68,9 @@ struct OtlpHttpExporterOptions

// TODO: Enable/disable to verify SSL certificate
std::chrono::milliseconds timeout = std::chrono::milliseconds(30000);

// filepath of the sll certifcate, this is empty if there is none.
std::string sslCertPath;
Copy link
Member

Choose a reason for hiding this comment

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

Should we use lower case to keep the same style as before?

// TODO: support ssl cert verification for https request
curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYPEER, 0); // 1L
curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYHOST, 0); // 2L
if (ssl_cert_path.empty()){
Copy link
Member

Choose a reason for hiding this comment

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

I think it's better to use a option use_ssl_credentials to control whether to ignore SSL verification which just like in OtlpGrpcExporterOptions.
And we should also privide options to set CURLOPT_SSLKEY and CURLOPT_SSLCERT .

@lalitb
Copy link
Member

lalitb commented Aug 4, 2021

@pavanshahm - Thanks for this PR. It would be good to have SSL certificate check integrated. A couple of comments here:

  1. Can we avoid adding code to build curl with SSL support as part of the otel-cpp build? I am not a bazel expert, but with cmake, we can build curl + SSL through vcpkg toolchain.
  2. instead of adding a certificate path, can we leverage the EventHandler class to pass the certificate:
    virtual void OnConnecting(const SSLCertificate &) noexcept {}

@lalitb
Copy link
Member

lalitb commented Aug 4, 2021

We need HTTPS here.If implementation SSL support for http server need a lot codes, maybe it's easier to use a third party library?

OK. I thought we don't really need to test the ssl-handshake as part of the unit test here, as it should work correctly with curl as long as the correct certificate is passed. We can locally add unit-test tests to ensure that the SSL certificate is set correctly through our HTTP client library. But we can discuss if you feel it is really required?

@owent
Copy link
Member

owent commented Aug 4, 2021

We need HTTPS here.If implementation SSL support for http server need a lot codes, maybe it's easier to use a third party library?

OK. I thought we don't really need to test the ssl-handshake as part of the unit test here, as it should work correctly with curl as long as the correct certificate is passed. We can locally add unit-test tests to ensure that the SSL certificate is set correctly through our HTTP client library. But we can discuss if you feel it is really required?

I don't think we need to test ssl-handshake either. But I think we should test whether the new options (sslCertPath) works. Is there any better suggestion to approach it?

@lalitb
Copy link
Member

lalitb commented Aug 5, 2021

We need HTTPS here.If implementation SSL support for http server need a lot codes, maybe it's easier to use a third party library?

OK. I thought we don't really need to test the ssl-handshake as part of the unit test here, as it should work correctly with curl as long as the correct certificate is passed. We can locally add unit-test tests to ensure that the SSL certificate is set correctly through our HTTP client library. But we can discuss if you feel it is really required?

I don't think we need to test ssl-handshake either. But I think we should test whether the new options (sslCertPath) works. Is there any better suggestion to approach it?

ok, I was thinking to avoid testing the HTTPS request path as part of the unit test if it needs us to build and link with a third-party library. On second thought - I had a quick look at civetweb usage in prometheus-cpp. Perhaps it can be a good replacement for internal http_server for both unit tests ( for http/https requests) and pages. But needs more discussion with other community members.

@lalitb
Copy link
Member

lalitb commented Aug 9, 2021

@pavanshahm - just wondering if you have plans to continue on this PR? As this has been at WIP state for some time now.

@lalitb
Copy link
Member

lalitb commented Sep 14, 2021

@pavanshahm - just wondering if you have plans to continue on this PR? As this has been at WIP state for some time now.

@pavanshahm - Checking one more time if you have plans to work on this PR. While it would be really good to get it merged, we also don't want to keep it stale for long.

@@ -68,6 +68,9 @@ struct OtlpHttpExporterOptions

// TODO: Enable/disable to verify SSL certificate
std::chrono::milliseconds timeout = std::chrono::milliseconds(30000);

// filepath of the sll certifcate, this is empty if there is none.
std::string sslCertPath;

Choose a reason for hiding this comment

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

mTLS support (requested by someone else here in another issue) will require two more fields for paths to private and public key. To avoid confusion please rename this field to make it more clear that this is path to trusted root CA certificates, e.g. sslCaCertPath.
In my issue I also asked about way to specify minimum TLS version (CURLOPT_SSLVERSION) and allowed ciphers (CURLOPT_SSL_CIPHER_LIST). Below I also mentioned another one to disable certificate validation. All of them would need corresponding fields here.
BTW, you also have typo in comment above - sll -> ssl

@@ -58,12 +58,20 @@ class Request : public http_client::Request
timeout_ms_ = timeout_ms;
}

void IncludePermissionsFilePath(std::string filepath) noexcept override

Choose a reason for hiding this comment

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

Other methods here uses nostd::string_view for parameters instead of std::string, please make it consistent.

// TODO: support ssl cert verification for https request
curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYPEER, 0); // 1L
curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYHOST, 0); // 2L
if (ssl_cert_path.empty()){

Choose a reason for hiding this comment

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

Empty CA cert path should mean that user wants to use default system path, not disable certificate validation. Ability to disable validation is another use case. Please add another option to disable certificate validation.

curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYHOST, 0); // 2L
} else {
curl_easy_setopt(curl_, CURLOPT_CAPATH, ssl_cert_path.c_str());
curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYPEER, 1);

Choose a reason for hiding this comment

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

This option is set by default to 1, so this line can be skipped.

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

Successfully merging this pull request may close these issues.

4 participants