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

Specify type for matching Subject Alternative Name. #18628

Merged
merged 58 commits into from
Nov 24, 2021

Conversation

pradeepcrao
Copy link
Contributor

@pradeepcrao pradeepcrao commented Oct 14, 2021

Fixes #18259

Signed-off-by: Pradeep Rao pcrao@google.com

Commit Message:
Additional Description:
Risk Level: Low
Testing: Added test
Docs Changes:
Release Notes:
Platform Specific Features:

Signed-off-by: Pradeep Rao <pcrao@google.com>
@repokitteh-read-only
Copy link

CC @envoyproxy/api-shepherds: Your approval is needed for changes made to api/envoy/.
envoyproxy/api-shepherds assignee is @adisuissa
CC @envoyproxy/api-watchers: FYI only for changes made to api/envoy/.

🐱

Caused by: #18628 was opened by pradeepcrao.

see: more, trace.

//
// .. attention::
//
// Subject Alternative Names are easily spoofable and verifying only them is insecure,
// therefore this option must be used together with :ref:`trusted_ca
// <envoy_v3_api_field_extensions.transport_sockets.tls.v3.CertificateValidationContext.trusted_ca>`.
repeated type.matcher.v3.StringMatcher match_subject_alt_names = 9;
repeated SubjectAltNameMatcher match_subject_alt_names_with_type = 14;
Copy link
Contributor

Choose a reason for hiding this comment

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

An alternative API that I think is simpler is to have a message of StringMatcher and an enum for the type of match. Thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That was exactly my first pass implementation. However, I could not find a simple way to extend it to support OtherName (eg. Microsoft UPN), the value for which could be a string or a complex message.

Copy link
Contributor

Choose a reason for hiding this comment

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

Jus thinking out loud here: if the typical use-case is using on of the types noted below, then it might make sense to have a oneof that includes either a typed-extension or a message that includes the enum+StringMatcher (example).

Copy link
Contributor

Choose a reason for hiding this comment

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

I think this would need lot of control planes to know about the type of SAN - which forces all the existing APIs to add the type (like DestintationRule API) in Istio which treats SANs as string. IMO this leads to lot of churn. Can we also accept ANY in enum so that if some one specifies ANY it does not mandate the type check? or leave both fields (do not deprecate the match_subject_alt_names)

cc: @howardjohn

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hi Rama, Howard,
the current change is needed to fix #18259 and having ANY in the enum or not deprecating match_subject_alt_names breaks the fix. Istio, etc. can keep utilizing the deprecated san matcher field for now, and use the deprecation window to modify their apis for correctness with respect to RFC 6125.

Copy link
Contributor

Choose a reason for hiding this comment

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

Consider renaming to match_typed_subject_alt_names.

But neither of these names are really correct, because this type allows either a typed-matcher, or a typed_config which could be anything. But I'm failing to think of a good name for this.

Signed-off-by: Pradeep Rao <pcrao@google.com>
Signed-off-by: Pradeep Rao <pcrao@google.com>
Signed-off-by: Pradeep Rao <pcrao@google.com>
Signed-off-by: Pradeep Rao <pcrao@google.com>
Copy link
Contributor

@adisuissa adisuissa left a comment

Choose a reason for hiding this comment

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

Thanks for fixing this!
Left a few API comments

@@ -253,7 +254,11 @@ message CertificateProviderPluginInstance {
string certificate_name = 2;
}

// [#next-free-field: 14]
message SubjectAltNameMatcher {
Copy link
Contributor

Choose a reason for hiding this comment

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

Please add comments describing the message and field.

@@ -253,7 +254,11 @@ message CertificateProviderPluginInstance {
string certificate_name = 2;
}

// [#next-free-field: 14]
message SubjectAltNameMatcher {
google.protobuf.Any typed_config = 1;
Copy link
Contributor

Choose a reason for hiding this comment

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

This type should be TypedExtensionConfig, as it is more strict.

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually, is there an added value to use the wrapper message (SubjectAltNameMatcher) rather than just repeated core.v3.TypedExtensionConfig?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My hope was that the wrapper provides some "type enforcing" in the certificate validation context C++ classes, and helps map back to the right message in the config.

I'll switch to TypeExtensionConfig.

//
// .. attention::
//
// Subject Alternative Names are easily spoofable and verifying only them is insecure,
// therefore this option must be used together with :ref:`trusted_ca
// <envoy_v3_api_field_extensions.transport_sockets.tls.v3.CertificateValidationContext.trusted_ca>`.
repeated type.matcher.v3.StringMatcher match_subject_alt_names = 9;
repeated SubjectAltNameMatcher match_subject_alt_names_with_type = 14;
Copy link
Contributor

Choose a reason for hiding this comment

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

Jus thinking out loud here: if the typical use-case is using on of the types noted below, then it might make sense to have a oneof that includes either a typed-extension or a message that includes the enum+StringMatcher (example).

@pradeepcrao
Copy link
Contributor Author

With regards to having enum + StringMatcher, the enums would need to be one of the pound defines here: https://boringssl.googlesource.com/boringssl/+/refs/heads/master/include/openssl/x509v3.h#174 or an identifier type from here https://datatracker.ietf.org/doc/html/rfc6125#section-1.8

The issue is that a Stringmatcher would not make sense for every enum value, just the ones we support today.

My initial implementation was exactly that : enum + Stringmatcher instead of a typed config. I changed it when the above was pointed out to me.

Does that sound reasonable?

@adisuissa
Copy link
Contributor

With regards to having enum + StringMatcher, the enums would need to be one of the pound defines here: https://boringssl.googlesource.com/boringssl/+/refs/heads/master/include/openssl/x509v3.h#174 or an identifier type from here https://datatracker.ietf.org/doc/html/rfc6125#section-1.8

The issue is that a Stringmatcher would not make sense for every enum value, just the ones we support today.

My initial implementation was exactly that : enum + Stringmatcher instead of a typed config. I changed it when the above was pointed out to me.

Does that sound reasonable?

I guess that if most use just a string matcher, then an enum + StringMatcher should be used to simplify the code, and a TypedExtension can be used to define the Other or some alternative that we don't support out of the box.
Specifically I suggest to have a generic string matcher message:

message StringSanMatcher {
  MatcherTypeEnum type = 1;
  type.matcher.v3.StringMatcher matcher = 2;
}

and the wrapper message message will use either the string matcher or the TypedExtension:

message SubjectAltNameMatcher {
  oneof {
    StringSanMatcher string_matcher = 1;
    core.v3.TypedExtensionConfig typed_config = 2;
  }
}

Note that this holds as long as we don't expect additional fields to the derived types (e.g., if UriSanMatcher will probably have an additional field later, then the current design may be better).

// match_subject_alt_names_with_type:
// typed_config:
// "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.common.DnsSanMatcher
// exact: "api.example.com"
//
// .. attention::
//
// Subject Alternative Names are easily spoofable and verifying only them is insecure,
// therefore this option must be used together with :ref:`trusted_ca
// <envoy_v3_api_field_extensions.transport_sockets.tls.v3.CertificateValidationContext.trusted_ca>`.
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you improve the comment by mentioning that this has an Any semantics (the SAN is verified if at least one of the matchers is matched)

StringSanMatchers or TypedExtensionConfigs for san matchers. Made test
regexes stricter.

Signed-off-by: Pradeep Rao <pcrao@google.com>
Signed-off-by: Pradeep Rao <pcrao@google.com>
Signed-off-by: Pradeep Rao <pcrao@google.com>
Signed-off-by: Pradeep Rao <pcrao@google.com>
Signed-off-by: Pradeep Rao <pcrao@google.com>
@@ -1,10 +1,13 @@
#include "source/common/ssl/certificate_validation_context_config_impl.h"

#include "envoy/common/exception.h"
#include "envoy/config/core/v3/extension.pb.h"
#include "envoy/extensions//transport_sockets/tls/v3/common.pb.h"
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this is what causing your format error.

Suggested change
#include "envoy/extensions//transport_sockets/tls/v3/common.pb.h"
#include "envoy/extensions/transport_sockets/tls/v3/common.pb.h"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks! Great catch!

Signed-off-by: Pradeep Rao <pcrao@google.com>
Signed-off-by: Pradeep Rao <pcrao@google.com>
@yanavlasov yanavlasov self-assigned this Oct 19, 2021
Signed-off-by: Pradeep Rao <pcrao@google.com>
Signed-off-by: Pradeep Rao <pcrao@google.com>
Signed-off-by: Pradeep Rao <pcrao@google.com>
Signed-off-by: Pradeep Rao <pcrao@google.com>
Signed-off-by: Pradeep Rao <pcrao@google.com>
@pradeepcrao
Copy link
Contributor Author

/retest

@repokitteh-read-only
Copy link

Retrying Azure Pipelines:
Check envoy-presubmit didn't fail.

🐱

Caused by: a #18628 (comment) was created by @pradeepcrao.

see: more, trace.

Signed-off-by: Pradeep Rao <pcrao@google.com>
Copy link
Contributor

@ggreenway ggreenway left a comment

Choose a reason for hiding this comment

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

This is looking pretty good. A few more tasks:

  • Please convert all tests that use match_subject_alt_names to the new config (so that removing the deprecated config in the future is painless)
  • Add a small amount of test coverage to ensure the now-deprecated match_subject_alt_names works as expected, eg it matches on any of the SAN types.

/wait

}

// Specification of type of SAN. Note that the default enum value is an invalid choice.
SanType san_type = 1 [(validate.rules).enum = {defined_only: true not_in: 0}];
Copy link
Contributor

Choose a reason for hiding this comment

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

I apologize; I totally missed that while reading this. Looks good; sorry for the hassle.

@@ -0,0 +1,47 @@
#include "source/extensions/transport_sockets/tls/cert_validator/san_matcher_config.h"
Copy link
Contributor

Choose a reason for hiding this comment

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

Rename files: san_matcher.cc/h

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.

@@ -290,24 +290,28 @@ bool DefaultCertValidator::verifySubjectAltName(X509* cert,
return false;
}

bool DefaultCertValidator::verifySubjectAltName(
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this function by part of SanMatcher? It's only called from there.

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.

san_matcher.set_san_type(
envoy::extensions::transport_sockets::tls::v3::
SubjectAltNameMatcher_SanType_SubjectAltNameMatcher_SanType_INT_MIN_SENTINEL_DO_NOT_USE_);
const SanMatcherPtr matcher = createStringSanMatcher(san_matcher);
Copy link
Contributor

Choose a reason for hiding this comment

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

The invalid enum shouldn't be possible due to proto validation. And even if it were possible, shouldn't this hit the RELEASE_ASSERT in this function? I don't think this test case is needed.

Copy link
Contributor Author

@pradeepcrao pradeepcrao Nov 18, 2021

Choose a reason for hiding this comment

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

I added the test case because CI failed due to of coverage numbers reducing (as NOT_REACHED_GCOVR_EXCL_LINE does not work as advertised anymore).

case envoy::extensions::transport_sockets::tls::v3::SubjectAltNameMatcher::IP_ADDRESS:
return Envoy::Ssl::SanMatcherPtr{std::make_unique<IpAddSanMatcher>(matcher.matcher())};
default:
RELEASE_ASSERT(true, "Invalid san type for "
Copy link
Contributor

Choose a reason for hiding this comment

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

This should be RELEASE_ASSERT(false, ......)

Signed-off-by: Pradeep Rao <pcrao@google.com>
Signed-off-by: Pradeep Rao <pcrao@google.com>
case envoy::extensions::transport_sockets::tls::v3::SubjectAltNameMatcher::IP_ADDRESS:
return SanMatcherPtr{std::make_unique<StringSanMatcher>(GEN_IPADD, matcher.matcher())};
default:
NOT_REACHED_GCOVR_EXCL_LINE;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

As expected this leads to a reduction in coverage by 0.1% and causes CI to fail.
https://storage.googleapis.com/envoy-pr/fd2b974/coverage/source/extensions/transport_sockets/tls/cert_validator/san_matcher.cc.gcov.html

@ggreenway do you know of a way I can overcome this?

Copy link
Contributor

Choose a reason for hiding this comment

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

You can modify test/per_file_coverage.sh to lower the required coverage.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks!

Signed-off-by: Pradeep Rao <pcrao@google.com>
Copy link
Contributor

@adisuissa adisuissa left a comment

Choose a reason for hiding this comment

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

/lgtm api

@pradeepcrao
Copy link
Contributor Author

/retest

@repokitteh-read-only
Copy link

Retrying Azure Pipelines:
Retried failed jobs in: envoy-presubmit

🐱

Caused by: a #18628 (comment) was created by @pradeepcrao.

see: more, trace.

@pradeepcrao
Copy link
Contributor Author

Hi @ggreenway, does this look good now? Do you have any pending concerns?

@yanavlasov yanavlasov dismissed ggreenway’s stale review November 24, 2021 14:27

All requested changes have been addressed

@yanavlasov yanavlasov merged commit bb95af8 into envoyproxy:main Nov 24, 2021
mpuncel added a commit to mpuncel/envoy that referenced this pull request Nov 30, 2021
* main: (77 commits)
  Fix verify_and_print_latest_release logic (envoyproxy#19111)
  http2: drain only once when reached max_requests_per_connection (envoyproxy#19078)
  Overload: Reset H2 server stream only use codec level reset mechanism (envoyproxy#18895)
  Update QUICHE from c2ddf95dc to 7f2d442e3 (envoyproxy#19095)
  tools: Fix dependency checker release dates bug (envoyproxy#19109)
  cve_scan: Use `envoy.dependency.cve_scan` (envoyproxy#19047)
  tcp: fix overenthusiastic bounds on the new pool (envoyproxy#19036)
  dep: update Proxy-Wasm C++ host (2021-11-18). (envoyproxy#19074)
  build(deps): bump frozendict from 2.0.7 to 2.1.0 in /tools/base (envoyproxy#19080)
  kafka: dependency upgrades (envoyproxy#18995)
  build(deps): bump charset-normalizer in /tools/dependency (envoyproxy#19105)
  build(deps): bump slack-sdk in /.github/actions/pr_notifier (envoyproxy#19093)
  dep: Remove dependency - six (envoyproxy#19085)
  Remove requested_server_name_ field from StreamInfo (envoyproxy#19102)
  broken link path fix for items http_filters/grpc_json_transcoder_filter (envoyproxy#19101)
  quic: turn off GRO (envoyproxy#19088)
  Listener: Add global conn limit opt out. (envoyproxy#18876)
  Specify type for matching Subject Alternative Name. (envoyproxy#18628)
  Fix a broken example in Lua filter docs (envoyproxy#19086)
  Fix a small typo (envoyproxy#19058)
  ...

Signed-off-by: Michael Puncel <mpuncel@squareup.com>
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.

TLS: allow specification of both type and value for SAN matcher
7 participants