Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
3c47ebb
Specify type for matching Subject Alternative Name.
pradeepcrao Oct 14, 2021
a554236
Fix build and presubmit issues
pradeepcrao Oct 14, 2021
9d3a7e9
Merge remote-tracking branch 'upstream/main' into san_matcher
pradeepcrao Oct 14, 2021
3d6272e
fix build
pradeepcrao Oct 14, 2021
f3c87a6
fix whitespace
pradeepcrao Oct 14, 2021
ff9cd5f
Added StringSanMatcher message, and the ability to provide either
pradeepcrao Oct 17, 2021
7287a34
Merge remote-tracking branch 'upstream/main' into san_matcher
pradeepcrao Oct 17, 2021
3aae6db
Fix formatting
pradeepcrao Oct 18, 2021
ab5cd11
Fix formatting.
pradeepcrao Oct 18, 2021
135391e
Fix formatting
pradeepcrao Oct 18, 2021
2a65d30
Fix include
pradeepcrao Oct 18, 2021
086ece5
Merge remote-tracking branch 'upstream/main' into san_matcher
pradeepcrao Oct 18, 2021
42c2f75
Merge remote-tracking branch 'upstream/main' into san_matcher
pradeepcrao Oct 19, 2021
e028388
Fix merge issue
pradeepcrao Oct 19, 2021
cebac65
Fix formatting.
pradeepcrao Oct 19, 2021
e8226dd
Fix spiffe validator.
pradeepcrao Oct 21, 2021
b083021
Merge remote-tracking branch 'upstream/main' into san_matcher
pradeepcrao Oct 21, 2021
af0c18b
Address review comments.
pradeepcrao Oct 21, 2021
bdc7c4e
Merge remote-tracking branch 'upstream/main' into san_matcher
pradeepcrao Oct 21, 2021
67d05d1
Remove TypedExtensionConfig for san matcher.
pradeepcrao Oct 27, 2021
b4bb871
Merge remote-tracking branch 'upstream/main' into san_matcher
pradeepcrao Oct 27, 2021
0d880c0
Fix integration test.
pradeepcrao Oct 27, 2021
7970de4
Fix doc issues.
pradeepcrao Oct 27, 2021
35265c6
Merge remote-tracking branch 'upstream/main' into san_matcher
pradeepcrao Oct 27, 2021
d5e2ec4
Address CI failures.
pradeepcrao Nov 2, 2021
9901676
Merge remote-tracking branch 'upstream/main' into san_matcher
pradeepcrao Nov 2, 2021
4af6264
Address CI failures.
pradeepcrao Nov 2, 2021
f6eefd6
Merge remote-tracking branch 'upstream/main' into san_matcher
pradeepcrao Nov 2, 2021
caec188
Merge remote-tracking branch 'upstream/main' into san_matcher
pradeepcrao Nov 2, 2021
b1b0261
Add test for san matcher config
pradeepcrao Nov 3, 2021
831ad94
Merge remote-tracking branch 'upstream/main' into san_matcher
pradeepcrao Nov 3, 2021
947da60
Address review comments.
pradeepcrao Nov 4, 2021
711b024
Merge remote-tracking branch 'upstream/main' into san_matcher
pradeepcrao Nov 4, 2021
c0113a9
Address review comment.
pradeepcrao Nov 4, 2021
7bcd271
Merge remote-tracking branch 'upstream/main' into san_matcher
pradeepcrao Nov 4, 2021
d0e365b
Fix format issue.
pradeepcrao Nov 4, 2021
bb5dc55
Merge remote-tracking branch 'upstream/main' into san_matcher
pradeepcrao Nov 4, 2021
14b6c0f
Address feedback.
pradeepcrao Nov 5, 2021
5ee23dd
Merge remote-tracking branch 'upstream/main' into san_matcher
pradeepcrao Nov 5, 2021
b4d8863
Fix spelling.
pradeepcrao Nov 8, 2021
cd8d388
Merge remote-tracking branch 'upstream/main' into san_matcher
pradeepcrao Nov 8, 2021
e8c36bb
Fix format issues.
pradeepcrao Nov 8, 2021
6adfb56
Merge remote-tracking branch 'upstream/main' into san_matcher
pradeepcrao Nov 8, 2021
d94cc3e
Address comments.
pradeepcrao Nov 8, 2021
b1bfe77
Merge remote-tracking branch 'upstream/main' into san_matcher
pradeepcrao Nov 8, 2021
d4dd073
Address feedback.
pradeepcrao Nov 10, 2021
3bc3cb6
Merge remote-tracking branch 'upstream/main' into san_matcher
pradeepcrao Nov 10, 2021
e034baf
Address feedback.
pradeepcrao Nov 10, 2021
d8aaafb
Merge remote-tracking branch 'upstream/main' into san_matcher
pradeepcrao Nov 10, 2021
de0525a
Undo e034baf to fix coverage.
pradeepcrao Nov 11, 2021
cc2b181
Merge remote-tracking branch 'upstream/main' into san_matcher
pradeepcrao Nov 11, 2021
00f151c
Merge remote-tracking branch 'upstream/main' into san_matcher
pradeepcrao Nov 12, 2021
36226ea
Address feedback.
pradeepcrao Nov 16, 2021
133a6a8
Merge remote-tracking branch 'upstream/main' into san_matcher
pradeepcrao Nov 16, 2021
c5b05ab
Merge remote-tracking branch 'upstream/main' into san_matcher
pradeepcrao Nov 17, 2021
05fb9b0
Address feedback.
pradeepcrao Nov 18, 2021
d97b59f
Merge remote-tracking branch 'upstream/main' into san_matcher
pradeepcrao Nov 18, 2021
6ceb50d
Modify coverage to account for unreached line.
pradeepcrao Nov 18, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 37 additions & 4 deletions api/envoy/extensions/transport_sockets/tls/v3/common.proto
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import "envoy/type/matcher/v3/string.proto";
import "google/protobuf/any.proto";
import "google/protobuf/wrappers.proto";

import "envoy/annotations/deprecation.proto";
import "udpa/annotations/migrate.proto";
import "udpa/annotations/sensitive.proto";
import "udpa/annotations/status.proto";
Expand Down Expand Up @@ -253,7 +254,29 @@ message CertificateProviderPluginInstance {
string certificate_name = 2;
}

// [#next-free-field: 14]
// String matcher for subject alternative names, to match both type and value of the SAN.
message StringSanMatcher {
enum SanType {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please add a comment here with the link to the relevant RFC section.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added comment.

EMAIL_ID = 0;
DNS_ID = 1;
URI_ID = 2;
Comment thread
mathetake marked this conversation as resolved.
Outdated
IP_ADD = 3;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

IP_ADDRESS

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

}

SanType san_type = 1 [(validate.rules).enum.defined_only = true];

type.matcher.v3.StringMatcher matcher = 2;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think this can be annotated with [(validate.rules).message = {required: true}].
Can you also add some comments to the fields.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Modified existing rule to exclude default value. Added comments.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

IIUC this allows a config with a defined san_type, but without any matcher. Is that the intent?
If not, consider adding the PGV rule: [(validate.rules).message = {required: true}] to this field

}

message SubjectAltNameMatcher {

Copy link
Copy Markdown
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.

oneof matcher {
StringSanMatcher string_matcher = 1;

config.core.v3.TypedExtensionConfig typed_config = 2;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we need this extension point? If someone needs to extend, can they just do it as custom_validator_config?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

To me, it makes more sense to have the extension point, as the string matcher does not work for all san types, and it is specifically only the san matcher that needs special handling in those cases, and not the entire validator config. Does that sound like a reasonable argument to you?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is anyone actually going to write an extension for this extension point? Or is it just hypothetical need?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The extension is needed to support OtherName as defined on page 38 here https://www.rfc-editor.org/rfc/pdfrfc/rfc5280.txt.pdf, which can be any user-defined type. As of now Envoy does not support this, but we will need to add it in the future if we would want to support SRV-ID or UPN (User Principle Name) which are othernames.
Should we just add the typed_config field in the future when support for these is needed?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Unless someone plans to add that support in the immediate future, I'd rather not add it until it's used. If it is added and never used, it creates extra maintenance burden for no gain.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Sounds good to me.

}
}

// [#next-free-field: 15]
message CertificateValidationContext {
option (udpa.annotations.versioning).previous_message_type =
"envoy.api.v2.auth.CertificateValidationContext";
Expand Down Expand Up @@ -388,6 +411,8 @@ message CertificateValidationContext {

// An optional list of Subject Alternative name matchers. If specified, Envoy will verify that the
// Subject Alternative Name of the presented certificate matches one of the specified matchers.
// The matching uses "any" semantics, that is to say, the SAN is verified if at least one matcher is
// matched.
//
// When a certificate has wildcard DNS SAN entries, to match a specific client, it should be
// configured with exact match type in the :ref:`string matcher <envoy_v3_api_msg_type.matcher.v3.StringMatcher>`.
Expand All @@ -396,15 +421,23 @@ message CertificateValidationContext {
//
// .. code-block:: yaml
//
// match_subject_alt_names:
// exact: "api.example.com"
// match_subject_alt_names_with_type:
// string_matcher:
// san_type: DNS_ID

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

san_type: DNS

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

// matcher:
// 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
Copy Markdown
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)

repeated type.matcher.v3.StringMatcher match_subject_alt_names = 9;
repeated SubjectAltNameMatcher match_subject_alt_names_with_type = 14;

Copy link
Copy Markdown
Member

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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
Member

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.


// This field is deprecated in favor of ref:`match_subject_alt_names_with_type
// <envoy_v3_api_field_extensions.transport_sockets.tls.v3.CertificateValidationContext.match_subject_alt_names_with_type>`
repeated type.matcher.v3.StringMatcher match_subject_alt_names = 9
[deprecated = true, (envoy.annotations.deprecated_at_minor_version) = "3.0"];

// [#not-implemented-hide:] Must present signed certificate time-stamp.
google.protobuf.BoolValue require_signed_certificate_timestamp = 6;
Expand Down
1 change: 1 addition & 0 deletions envoy/ssl/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ envoy_cc_library(
external_deps = ["abseil_optional"],
deps = [
"//source/common/common:matchers_lib",
"@envoy_api//envoy/config/core/v3:pkg_cc_proto",
"@envoy_api//envoy/extensions/transport_sockets/tls/v3:pkg_cc_proto",
"@envoy_api//envoy/type/matcher/v3:pkg_cc_proto",
],
Expand Down
27 changes: 26 additions & 1 deletion envoy/ssl/certificate_validation_context_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,39 @@

#include "envoy/api/api.h"
#include "envoy/common/pure.h"
#include "envoy/config/core/v3/extension.pb.h"
#include "envoy/config/typed_config.h"
#include "envoy/extensions/transport_sockets/tls/v3/cert.pb.h"
#include "envoy/extensions/transport_sockets/tls/v3/common.pb.h"
#include "envoy/type/matcher/v3/string.pb.h"

#include "absl/types/optional.h"
#include "openssl/x509v3.h"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Putting this into an interface header may lead to complications with building various configurations of envoy. Please validate that envoy without any TLS extensions included still builds. Or move this interface to be internal to the tls transport_socket, and then we don't have to worry about it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Moved the interface.


namespace Envoy {
namespace Ssl {

/** Interface to verify if there is a match in a list of subject alternative
* names.
*/
class SanMatcher {
public:
virtual bool match(GENERAL_NAMES const*) const PURE;
virtual ~SanMatcher() = default;
};

using SanMatcherPtr = std::unique_ptr<SanMatcher>;

class SanMatcherFactory : public Config::TypedFactory {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Given that there isn't an extension point for this, why register a factory type?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yikes. I did have an extension point but did not remove this when I removed the extension point. Fixed.

public:
~SanMatcherFactory() override = default;

virtual SanMatcherPtr
createSanMatcher(const envoy::config::core::v3::TypedExtensionConfig* config) PURE;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It might be better to pass the config by reference, unless it can be null

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

sgtm


std::string category() const override { return "envoy.san_matchers"; }
};

class CertificateValidationContextConfig {
public:
virtual ~CertificateValidationContextConfig() = default;
Expand Down Expand Up @@ -43,7 +68,7 @@ class CertificateValidationContextConfig {
/**
* @return The subject alt name matchers to be verified, if enabled.
*/
virtual const std::vector<envoy::type::matcher::v3::StringMatcher>&
virtual const std::vector<envoy::extensions::transport_sockets::tls::v3::SubjectAltNameMatcher>&
subjectAltNameMatchers() const PURE;

/**
Expand Down
1 change: 1 addition & 0 deletions source/common/ssl/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ envoy_cc_library(
"//envoy/ssl:certificate_validation_context_config_interface",
"//source/common/common:empty_string",
"//source/common/config:datasource_lib",
"@envoy_api//envoy/config/core/v3:pkg_cc_proto",
"@envoy_api//envoy/extensions/transport_sockets/tls/v3:pkg_cc_proto",
"@envoy_api//envoy/type/matcher/v3:pkg_cc_proto",
],
Expand Down
34 changes: 32 additions & 2 deletions source/common/ssl/certificate_validation_context_config_impl.cc
Original file line number Diff line number Diff line change
@@ -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
Copy Markdown
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
Copy Markdown
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!

#include "envoy/extensions/transport_sockets/tls/v3/cert.pb.h"

#include "source/common/common/empty_string.h"
#include "source/common/common/fmt.h"
#include "source/common/common/logger.h"
#include "source/common/config/datasource.h"

namespace Envoy {
Expand All @@ -22,8 +25,7 @@ CertificateValidationContextConfigImpl::CertificateValidationContextConfigImpl(
certificate_revocation_list_path_(
Config::DataSource::getPath(config.crl())
.value_or(certificate_revocation_list_.empty() ? EMPTY_STRING : INLINE_STRING)),
subject_alt_name_matchers_(config.match_subject_alt_names().begin(),
config.match_subject_alt_names().end()),
subject_alt_name_matchers_(getSubjectAltNameMatchers(config)),
verify_certificate_hash_list_(config.verify_certificate_hash().begin(),
config.verify_certificate_hash().end()),
verify_certificate_spki_list_(config.verify_certificate_spki().begin(),
Expand All @@ -36,6 +38,7 @@ CertificateValidationContextConfigImpl::CertificateValidationContextConfigImpl(
config.custom_validator_config())
: absl::nullopt),
api_(api) {

if (ca_cert_.empty() && custom_validator_config_ == absl::nullopt) {
if (!certificate_revocation_list_.empty()) {
throw EnvoyException(fmt::format("Failed to load CRL from {} without trusted CA",
Expand All @@ -51,5 +54,32 @@ CertificateValidationContextConfigImpl::CertificateValidationContextConfigImpl(
}
}

std::vector<envoy::extensions::transport_sockets::tls::v3::SubjectAltNameMatcher>
CertificateValidationContextConfigImpl::getSubjectAltNameMatchers(
const envoy::extensions::transport_sockets::tls::v3::CertificateValidationContext& config) {
if (!config.match_subject_alt_names_with_type().empty() &&
!config.match_subject_alt_names().empty()) {
throw EnvoyException("SAN-based verification using both match_subject_alt_names_with_type and "
"the deprecated match_subject_alt_names is not allowed");
}
std::vector<envoy::extensions::transport_sockets::tls::v3::SubjectAltNameMatcher>
subject_alt_name_matchers(config.match_subject_alt_names_with_type().begin(),
config.match_subject_alt_names_with_type().end());
// Handle deprecated string type san matchers without san type specified, by
// creating backwards compatible san matcher configs.
for (auto& matcher : config.match_subject_alt_names()) {
subject_alt_name_matchers.emplace_back();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You may be able to iterate over the values [SanType_MIN, SanType_MAX] (see https://developers.google.com/protocol-buffers/docs/reference/cpp-generated#enum).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I'd rather be explicit here. If new enum types are added in the future, those should NOT be iterated over in this loop, as this is for backwards compatibility ONLY.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

So in this case I suggest to refactor the code to iterate over the specific set of enum values, and add them (decrease code duplication).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed

subject_alt_name_matchers.back().set_allocated_typed_config(
new ::envoy::config::core::v3::TypedExtensionConfig());
subject_alt_name_matchers.back().mutable_typed_config()->set_allocated_typed_config(
new ProtobufWkt::Any());
subject_alt_name_matchers.back().mutable_typed_config()->mutable_typed_config()->PackFrom(
matcher);
subject_alt_name_matchers.back().mutable_typed_config()->mutable_name()->assign(
"envoy.san_matchers.backward_compatible_san_matcher");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Instead of allocating new objects you should be able to create the TypedExtensionConfig object on the stack, and pack it into the mutable_typed_config() (see example here)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Aah, didn't realise that mutable_typed_config() allocates the typed config for you. Thanks.

}
return subject_alt_name_matchers;
}

} // namespace Ssl
} // namespace Envoy
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "envoy/api/api.h"
#include "envoy/extensions/transport_sockets/tls/v3/cert.pb.h"
#include "envoy/extensions/transport_sockets/tls/v3/common.pb.h"
#include "envoy/ssl/certificate_validation_context_config.h"
#include "envoy/type/matcher/v3/string.pb.h"

Expand All @@ -24,7 +25,7 @@ class CertificateValidationContextConfigImpl : public CertificateValidationConte
const std::string& certificateRevocationListPath() const final {
return certificate_revocation_list_path_;
}
const std::vector<envoy::type::matcher::v3::StringMatcher>&
const std::vector<envoy::extensions::transport_sockets::tls::v3::SubjectAltNameMatcher>&
subjectAltNameMatchers() const override {
return subject_alt_name_matchers_;
}
Expand All @@ -49,11 +50,15 @@ class CertificateValidationContextConfigImpl : public CertificateValidationConte
Api::Api& api() const override { return api_; }

private:
static std::vector<envoy::extensions::transport_sockets::tls::v3::SubjectAltNameMatcher>
getSubjectAltNameMatchers(
const envoy::extensions::transport_sockets::tls::v3::CertificateValidationContext& config);
const std::string ca_cert_;
const std::string ca_cert_path_;
const std::string certificate_revocation_list_;
const std::string certificate_revocation_list_path_;
const std::vector<envoy::type::matcher::v3::StringMatcher> subject_alt_name_matchers_;
const std::vector<envoy::extensions::transport_sockets::tls::v3::SubjectAltNameMatcher>
subject_alt_name_matchers_;
const std::vector<std::string> verify_certificate_hash_list_;
const std::vector<std::string> verify_certificate_spki_list_;
const bool allow_expired_certificate_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@ envoy_cc_library(
srcs = [
"default_validator.cc",
"factory.cc",
"san_matcher_config.cc",
"utility.cc",
],
hdrs = [
"cert_validator.h",
"default_validator.h",
"factory.h",
"san_matcher_config.h",
"utility.h",
],
external_deps = [
Expand All @@ -35,9 +37,13 @@ envoy_cc_library(
"//source/common/common:hex_lib",
"//source/common/common:minimal_logger_lib",
"//source/common/common:utility_lib",
"//source/common/config:utility_lib",
"//source/common/stats:symbol_table_lib",
"//source/common/stats:utility_lib",
"//source/extensions/transport_sockets/tls:stats_lib",
"//source/extensions/transport_sockets/tls:utility_lib",
"@envoy_api//envoy/config/core/v3:pkg_cc_proto",
"@envoy_api//envoy/extensions/transport_sockets/tls/v3:pkg_cc_proto",
"@envoy_api//envoy/type/matcher/v3:pkg_cc_proto",
],
)
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@
#include "source/common/common/hex.h"
#include "source/common/common/matchers.h"
#include "source/common/common/utility.h"
#include "source/common/config/utility.h"
#include "source/common/network/address_impl.h"
#include "source/common/protobuf/utility.h"
#include "source/common/runtime/runtime_features.h"
#include "source/common/stats/symbol_table_impl.h"
#include "source/common/stats/utility.h"
#include "source/extensions/transport_sockets/tls/cert_validator/cert_validator.h"
#include "source/extensions/transport_sockets/tls/cert_validator/factory.h"
#include "source/extensions/transport_sockets/tls/cert_validator/san_matcher_config.h"
#include "source/extensions/transport_sockets/tls/cert_validator/utility.h"
#include "source/extensions/transport_sockets/tls/stats.h"
#include "source/extensions/transport_sockets/tls/utility.h"
Expand Down Expand Up @@ -144,9 +146,19 @@ int DefaultCertValidator::initializeSslContexts(std::vector<SSL_CTX*> contexts,
const Envoy::Ssl::CertificateValidationContextConfig* cert_validation_config = config_;
if (cert_validation_config != nullptr) {
if (!cert_validation_config->subjectAltNameMatchers().empty()) {
for (const envoy::type::matcher::v3::StringMatcher& matcher :
for (const envoy::extensions::transport_sockets::tls::v3::SubjectAltNameMatcher& matcher :
cert_validation_config->subjectAltNameMatchers()) {
subject_alt_name_matchers_.push_back(Matchers::StringMatcherImpl(matcher));
if (matcher.has_string_matcher()) {
subject_alt_name_matchers_.emplace_back(createStringSanMatcher(matcher.string_matcher()));
} else {
auto const factory =
Envoy::Config::Utility::getAndCheckFactory<Envoy::Ssl::SanMatcherFactory>(
matcher.typed_config(), true);
if (factory != nullptr) {
subject_alt_name_matchers_.emplace_back(
factory->createSanMatcher(&matcher.typed_config()));
}
}
}
verify_mode = verify_mode_validation_context;
}
Expand Down Expand Up @@ -218,8 +230,8 @@ int DefaultCertValidator::doVerifyCertChain(

// If `trusted_ca` exists, it is already verified in the code above. Thus, we just need to make
// sure the verification for other validation context configurations doesn't fail (i.e. either
// `NotValidated` or `Validated`). If `trusted_ca` doesn't exist, we will need to make sure other
// configurations are verified and the verification succeed.
// `NotValidated` or `Validated`). If `trusted_ca` doesn't exist, we will need to make sure
// other configurations are verified and the verification succeed.
int validation_status = verify_trusted_ca_
? validated != Envoy::Ssl::ClientValidationStatus::Failed
: validated == Envoy::Ssl::ClientValidationStatus::Validated;
Expand All @@ -229,8 +241,7 @@ int DefaultCertValidator::doVerifyCertChain(

Envoy::Ssl::ClientValidationStatus DefaultCertValidator::verifyCertificate(
X509* cert, const std::vector<std::string>& verify_san_list,
const std::vector<Matchers::StringMatcherImpl<envoy::type::matcher::v3::StringMatcher>>&
subject_alt_name_matchers) {
const std::vector<Envoy::Ssl::SanMatcherPtr>& subject_alt_name_matchers) {
Envoy::Ssl::ClientValidationStatus validated = Envoy::Ssl::ClientValidationStatus::NotValidated;

if (!verify_san_list.empty()) {
Expand Down Expand Up @@ -308,26 +319,28 @@ bool DefaultCertValidator::dnsNameMatch(const absl::string_view dns_name,
return false;
}

bool DefaultCertValidator::verifySubjectAltName(

Copy link
Copy Markdown
Member

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
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

const GENERAL_NAME* general_name,
Matchers::StringMatcherImpl<envoy::type::matcher::v3::StringMatcher> const& matcher) {
// For DNS SAN, if the StringMatcher type is exact, we have to follow DNS matching semantics.
const std::string san = Utility::generalNameAsString(general_name);
return general_name->type == GEN_DNS &&
matcher.matcher().match_pattern_case() ==
envoy::type::matcher::v3::StringMatcher::MatchPatternCase::kExact
? dnsNameMatch(matcher.matcher().exact(), absl::string_view(san))
: matcher.match(san);
}

bool DefaultCertValidator::matchSubjectAltName(
X509* cert,
const std::vector<Matchers::StringMatcherImpl<envoy::type::matcher::v3::StringMatcher>>&
subject_alt_name_matchers) {
X509* cert, const std::vector<Envoy::Ssl::SanMatcherPtr>& subject_alt_name_matchers) {
bssl::UniquePtr<GENERAL_NAMES> san_names(
static_cast<GENERAL_NAMES*>(X509_get_ext_d2i(cert, NID_subject_alt_name, nullptr, nullptr)));
if (san_names == nullptr) {
return false;
}
for (const GENERAL_NAME* general_name : san_names.get()) {
const std::string san = Utility::generalNameAsString(general_name);
for (auto& config_san_matcher : subject_alt_name_matchers) {
// For DNS SAN, if the StringMatcher type is exact, we have to follow DNS matching semantics.
if (general_name->type == GEN_DNS &&
config_san_matcher.matcher().match_pattern_case() ==
envoy::type::matcher::v3::StringMatcher::MatchPatternCase::kExact
? dnsNameMatch(config_san_matcher.matcher().exact(), absl::string_view(san))
: config_san_matcher.match(san)) {
return true;
}
for (auto& config_san_matcher : subject_alt_name_matchers) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

const auto&?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

if (config_san_matcher->match(san_names.get())) {
return true;
}
}
return false;
Expand Down
Loading