-
Notifications
You must be signed in to change notification settings - Fork 55
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 TLS testing #150
add TLS testing #150
Conversation
Adds the first pass at TLS helpers and integration with tests. https works now, grpc does not and needs more work
There's still more work to do. --no-tls-verify does not seem to work as expected and that needs figuring out and tested. Also need to add tests for client cert authentication. But this all works and the certs generated seem valid. Added diagnistic for no-tls-verify. Added setting a cacert in the root bundle in otel-cli. Need to double-check this is the right behavior to ship. Cacert config needs to be added to HTTPs as well if ^^ turns up as the behavior being correct.
otelcli/root.go
Outdated
@@ -67,6 +67,10 @@ func addClientParams(cmd *cobra.Command) { | |||
cmd.Flags().StringToStringVar(&config.Headers, "otlp-headers", defaults.Headers, "a comma-sparated list of key=value headers to send on OTLP connection") | |||
cmd.Flags().BoolVar(&config.Blocking, "otlp-blocking", defaults.Blocking, "block on connecting to the OTLP server before proceeding") | |||
|
|||
cmd.Flags().StringVar(&config.Certificate, "cacert", defaults.Certificate, "a file containing the server's CA certificate") | |||
cmd.Flags().StringVar(&config.ClientCert, "client-cert", defaults.ClientCert, "a file containing the client certificate") | |||
cmd.Flags().StringVar(&config.ClientKey, "client-key", defaults.ClientKey, "a file containing the client certificate key") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
^^ need feedback on these. Do they look ok? Should there be a set of --tls-* options?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's dealer's choice if these should have a tls-
prefix. personally, I view adding a prefix now as more future-proof because over time we're likely to see more, not fewer, cli options, and we're probably not going to go back and change these, once committed, so we might as well make them explicit now. On the other hand, the flags that we add in future are unlikely to be cert related, so maybe the prefix is implied and we can skip it. Characters aren't too expensive (even in cli options) so i've talked myself into adding the prefix, but I don't see it as a major UX/comprehensibility issue either way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made the change, it looks better this way:
--tls-ca-cert string a file containing the certificate authority bundle
--tls-client-cert string a file containing the client certificate
--tls-client-key string a file containing the client certificate key
--tls-no-verify insecure! disables verification of the server certificate and name, mostly for self-signed CAs
--no-tls-verify (deprecated) same as --tls-no-verify
On the first pass of this code I wasn't sure what all I would need, so I put all the intermediate steps of the CA and certs in the struct. Now that some tests are running, it's clear some things don't need to be there and the code looks cleaner this way.
They were out of sync and it was silly to copy the code in this case. 🤔 and now it can be tested independently.
SubjectKeyId shouldn't have been there in the first place, I copied it and didn't trim it back. The IPAddresses doesn't seem to have an impact on removal so removing it too. The TLS config setups for server and client were both wrong. They shouldn't have had RootCAs set. Setting ServerName seems to have helped to get HTTP TLS working (but grpc still doesn't). Also setting ClientCAs on the server for when we start testing client cert auth.
See comment for explanation of bewilderment.
The way the tests passed before wasn't ideal but was good enough to call the approach to testing viable. Now that the TLS configs are sorted out, the tests pass under --no-tls-verify and further commits will add tests back for envvar and client auth.
Renamed config struct member to CACert. Made config file names match the opentelemetry collector yaml, for better or worse. Added TLS settings to the example config.
In the first pass I built up the CA and certs according to my outdated knowledge of building CAs with openssl and examples. Since Go doesn't really care much about a lot of the cert metadata I went through and stripped out as many superfluous fields as I could and keep tests passing. Less code is good :)
// injectVars replaces all instances of {{endpoint}}, {{cacert}}, {{client_cert}}, and | ||
// {{client_key}} with test values. | ||
// This is needed because the otlpserver is configured to listen on :0 which has it | ||
// grab a random port. Once that's generated we need to inject it into all the values |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: it would be slightly clearer to say:
Once generated, we need to inject the port into all the values so the test comparisons...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, discussion topics are non-blocking for commit
otelcli/root.go
Outdated
@@ -67,6 +67,10 @@ func addClientParams(cmd *cobra.Command) { | |||
cmd.Flags().StringToStringVar(&config.Headers, "otlp-headers", defaults.Headers, "a comma-sparated list of key=value headers to send on OTLP connection") | |||
cmd.Flags().BoolVar(&config.Blocking, "otlp-blocking", defaults.Blocking, "block on connecting to the OTLP server before proceeding") | |||
|
|||
cmd.Flags().StringVar(&config.Certificate, "cacert", defaults.Certificate, "a file containing the server's CA certificate") | |||
cmd.Flags().StringVar(&config.ClientCert, "client-cert", defaults.ClientCert, "a file containing the client certificate") | |||
cmd.Flags().StringVar(&config.ClientKey, "client-key", defaults.ClientKey, "a file containing the client certificate key") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's dealer's choice if these should have a tls-
prefix. personally, I view adding a prefix now as more future-proof because over time we're likely to see more, not fewer, cli options, and we're probably not going to go back and change these, once committed, so we might as well make them explicit now. On the other hand, the flags that we add in future are unlikely to be cert related, so maybe the prefix is implied and we can skip it. Characters aren't too expensive (even in cli options) so i've talked myself into adding the prefix, but I don't see it as a major UX/comprehensibility issue either way.
* Do NOT copy this code for production systems. It makes a few compromises to | ||
* optimize for testing and ephemeral certs that are totally inappropriate for | ||
* use in settings where security matters. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there any way to make this more forceful than a comment?
off the top of my head, perhaps some kind of output from the module that would flag the issue to an end user?
or maybe also add code comments that point out the specific compromises a cargo-cult-er needs to change?
and the last thought was adding some kind of friction here to make it hard to misuse, though I have no concrete ideas on how to go about that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh and one last thought was to add something akin to a comment in the output files so that anyone viewing their contents would investigate and find the comments in code
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since it's in the main_test
package it can't be directly used as a dependency and doesn't ship with the otel-cli binary. Someone would have to copy the file and modify it, or copy/paste to reuse the code, so risk is pretty low. I mostly wanted to say something and leave it as an exercise to the reader to figure out those compromises.
Per code review, I'm convinced that all the tls options should start with --tls for clarity so they've been renamed. --no-tls-verify has been renamed to --tls-no-verify. The old option is still supported but will be removed before 1.0.
No idea how this was so very wrong. Fixed now :)
Synopsis
This PR adds TLS testing capability to otel-cli's functional test harness, and to
make sure that functionality was complete enough to merge, I also added
client certificate authentication support. These are bundled because
I fixed some problems in otel-cli's TLS handling along the way. Hopefully this
will be the last big PR for a while. While on the large side of things, the bulk
of this code is the new TLS CA and tests.
Client Authentication
otel-cli can now directly authenticate to a server using a client certificate.
While this may have worked before via opentelemetry-go environment variables, we
could not call it a supported feature while not testing it, and not making it
work consistently with other otel-cli features (config & flags).
The new flags have been added with envvars and json keys. (note: I opened issue
#164 with a follow-up to fix the json keys):
--tls-ca-cert
,--tls-client-cert
, and--tls-client-key
.--no-tls-verify
is now deprecated and renamed to--tls-no-verify
so theprefix usage is consistent.
TLS Testing Design
Building on the existing functional tests,
tls_for_test.go
has been added, andimplements an ephemeral self-signed certificate authority. It generates
everything needed for the client and server side to run tests with full TLS.
It's fast enough I barely notice the difference compared to exec'ing otel-cli a
bunch. New template variables are available for test fixtures to inject
certificate and key files. When the OTLP HTTP and gRPC servers start, they will
optionally enable TLS and client cert auth as configured on the fixture.