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

feat: Add support for mutual TLS. #1556

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

megabus-tobin
Copy link

Add support for specifying client certificate and key for mutual TLS when exporting.

Also log more information about why an SSL error occured as this can be very difficult to diagnose. This is logged in the same way as other probably fatal issues are, e.g. HTTP 404s.

Copy link

linux-foundation-easycla bot commented Dec 21, 2023

CLA Signed

The committers listed above are authorized under a signed CLA.

  • ✅ login: megabus-tobin / name: Tobin Richard (384a6a9)

@arielvalentin
Copy link
Contributor

@megabus-tobin Thank you for your contribution!

Please consider separating the error handling changes in a separate PR. We will be able to review and release that change independent of verifying the correctness of the changes required for mTLS support.

Happy Holidays!

@megabus-tobin megabus-tobin changed the title feat: Add support for mutual TLS and improve SSL error logging. feat: Add support for mutual TLS. Dec 23, 2023
@megabus-tobin
Copy link
Author

megabus-tobin commented Dec 23, 2023

@arielvalentin I've split the small logging change off into #1557

Thanks!

Copy link
Contributor

@kaylareopelle kaylareopelle left a comment

Choose a reason for hiding this comment

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

Thank you, @megabus-tobin!

For anyone who's interested, the specs for these env vars can be found here: https://opentelemetry.io/docs/specs/otel/protocol/exporter/

Could you incorporate the new environment variables into the exporter tests? (here's the file for the OTLP library)

Anywhere the certificate_file is mentioned may be a good place to add content for the client certificate and key.

@megabus-tobin
Copy link
Author

Could you incorporate the new environment variables into the exporter tests? (here's the file for the OTLP library)

Anywhere the certificate_file is mentioned may be a good place to add content for the client certificate and key.

The Net:HTTP class makes this a bit harder than it should be. Unlike ca_cert, the cert and key members aren't strings, they're OpenSSL::X509::Certificate and OpenSSL::PKey::RSA objects.

I'm not sure what the best approach would be. Should I add a test certificate and key to the repository or refactor OpenTelemetry::Exporter::OTLP::Exporter.initialize to optionally take the object directly and fallback to trying to load them from the environment?

The latter would be very similar to what OpenTelemetry::Exporter::OTLP::Exporter.prepare_endpoint already does. It would also have the small advantage of allowing for more exotic ways of obtaining the certificate and key but the utility of that is questionable since you need a file for the CA cert anyway.

@kaylareopelle
Copy link
Contributor

The Net:HTTP class makes this a bit harder than it should be. Unlike ca_cert, the cert and key members aren't strings, they're OpenSSL::X509::Certificate and OpenSSL::PKey::RSA objects.

I'm not sure what the best approach would be. Should I add a test certificate and key to the repository or refactor OpenTelemetry::Exporter::OTLP::Exporter.initialize to optionally take the object directly and fallback to trying to load them from the environment?

The latter would be very similar to what OpenTelemetry::Exporter::OTLP::Exporter.prepare_endpoint already does. It would also have the small advantage of allowing for more exotic ways of obtaining the certificate and key but the utility of that is questionable since you need a file for the CA cert anyway.

Sorry for my delated response. Great questions! I think adding the test certificate and key seems the least intrusive to what you've already built if that's not too much effort. If other approvers/maintainers disagree, please chime in!

I like your idea about following the pattern in OpenTelemetry::Exporter::OTLP::Exporter.prepare_endpoint, but like you mentioned, I'm not sure about the utility of that approach.

Copy link
Contributor

github-actions bot commented Mar 7, 2024

👋 This pull request has been marked as stale because it has been open with no activity. You can: comment on the issue or remove the stale label to hold stale off for a while, add the keep label to hold stale off permanently, or do nothing. If you do nothing this pull request will be closed eventually by the stale bot

@github-actions github-actions bot added the stale label Mar 7, 2024
Add support for specifying client certificate and key for mutual TLS when exporting.
@megabus-tobin
Copy link
Author

@kaylareopelle I have updated the tests to check that the client certificate and key are handled correctly.

Some small notes:

  1. To test that explicit TLS settings are preferred to environment variables I needed a second cert/key that would be loaded in the unlikely event the test was going to fail.
  2. Initially I generated the cert/key on the fly but since a path is needed this would have made it necessary to ensure a writeable filesystem when running tests. Instead I have put the test certs/keys into the same directory as the tests and referenced that via __FILE__.
  3. The certs/keys I generated are obviously meaningless. E.g. CN = a.example.tld, O = Internet Widgits Pty Ltd. By the time this gets reviewed they will probably also be expired, which the tests don't care about.
  4. Rather than reading the certs/keys at the point of comparison, I've done it once near the top of the file. Apart from avoiding a little repetition this makes it much easier to spot if the files got removed, etc. rather than an individual test appearing to fail.

Copy link
Contributor

github-actions bot commented Apr 7, 2024

👋 This pull request has been marked as stale because it has been open with no activity. You can: comment on the issue or remove the stale label to hold stale off for a while, add the keep label to hold stale off permanently, or do nothing. If you do nothing this pull request will be closed eventually by the stale bot

@github-actions github-actions bot added the stale label Apr 7, 2024
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = uri.scheme == 'https'
http.verify_mode = ssl_verify_mode
http.ca_file = certificate_file unless certificate_file.nil?
http.cert = OpenSSL::X509::Certificate.new(File.read(client_certificate_file)) unless client_certificate_file.nil?
Copy link

Choose a reason for hiding this comment

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

Especially when running in containers, and using environment variables, it would be nice to be able to load the PEM encoded cert/key directly from environment variables, instead of having to find a way to write it to a file first.

Copy link
Author

Choose a reason for hiding this comment

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

I agree but at least one file will still be needed for many/most users because it's assigned to Net::HTTP#ca_file which can only be a path. Should I make the change to support either for the client cert and key despite that?

@szechyjs
Copy link

szechyjs commented May 6, 2024

Would be nice to update the gRPC exporter as well.

creds = if mtls_config_provided
  GRPC::Core::ChannelCredentials.new(ca, key, cert)
else
  :this_channel_is_insecure
end

@client = Opentelemetry::Proto::Collector::Trace::V1::TraceService::Stub.new(
  "#{uri.host}:#{uri.port}",
  creds
)

https://github.com/open-telemetry/opentelemetry-ruby/blob/main/exporter/otlp-grpc/lib/opentelemetry/exporter/otlp/grpc/trace_exporter.rb#L34

@github-actions github-actions bot removed the stale label May 9, 2024
@kaylareopelle
Copy link
Contributor

@kaylareopelle I have updated the tests to check that the client certificate and key are handled correctly.

@megabus-tobin, thank you for updating the tests! I think this is a solid approach.

Are you planning to make the GRPC changes mentioned here as part of this PR?

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.

None yet

4 participants