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

Feature untrusted client certs #9172

Merged

Conversation

jimini-lumox
Copy link
Contributor

Description: Add the ability to pass through and route 'untrusted' certificates.

This is a resurrection of PR #8248 with latest master merged, & changes to ssl-context routing merged, as requested in #8248.

The original PR covered two requirements:
Allowing certs that fail validation.
Request peer certs when there is nothing to validate against.
Support routing based on client credential validation status.

By default the client validation rules are unchanged.

Additional validation context options:
// Specify the certificate validation to be performed: VERIFY_TRUST_CHAIN(default), ACCEPT_UNTRUSTED, NOT_VERIFIED.
TrustChainVerification verify_certificate_trust_chain;

Added Routing support based on whether the client certificate was validated or not.

Risk Level: Medium
Testing: Manual and unit tests
Docs Changes: API proto changes
Release Notes: N/A

@repokitteh-read-only
Copy link

CC @envoyproxy/api-shepherds: Your approval is needed for changes made to api/.

🐱

Caused by: #9172 was opened by jimini-lumox.

see: more, trace.

@@ -349,6 +349,9 @@ message RouteMatch {
message TlsContextMatchOptions {
// If specified, the route will match against whether or not a certificate is presented.
google.protobuf.BoolValue presented = 1;

// If specified, the route will match against whether or not a certificate is validated.
google.protobuf.BoolValue validated = 2;
Copy link
Member

Choose a reason for hiding this comment

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

Ideally we make this an enum (and deprecate the old way of doing this).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

These fields are used for route matching, and are effectively a tribool - true/false/not-defined
eg: for 'validated', by default we don't route based on validation status, unless specifically set to true / false, example snippet from previous PR #8248 :

"routes": [
  {
    "match": { "prefix": "/", "credentials": { "validated": false } },
    "route": {
      "cluster": "venue-edge-access-control",
      ...
    }
  },
  {
    "match": { "prefix": "/", "credentials": { "validated": true },
               "headers": [ { "name": ":authority", "prefix_match": "service-actual-target-service" }
               ]
    },
    "route": {
      "cluster": "service-actual-target-service"
    }
  }
...

Copy link
Member

Choose a reason for hiding this comment

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

Ack. Is there a reason they are BoolValue other than history? What is the default value? If it's false, I suggest leaving a [#next-major-version: change type to bool] for both of these fields.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The default is that it is not specified so will not be routed against. It is only routed against if specified in the configuration. This is why we've used a BoolValue (like a tribool). Is there another recommended way of defining this?

api/envoy/api/v2/auth/cert.proto Outdated Show resolved Hide resolved
api/envoy/api/v2/auth/cert.proto Outdated Show resolved Hide resolved
@@ -301,11 +302,20 @@ void SslSocket::shutdownSsl() {
}
}

SslSocketInfo::SslSocketInfo(bssl::UniquePtr<SSL> ssl, ContextImplSharedPtr ctx)
: ssl_(std::move(ssl)) {
SSL_set_ex_data(ssl_.get(), ctx->sslCustomDataIndex(), &(this->certificate_validation_status_));
Copy link
Member

Choose a reason for hiding this comment

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

Not thrilled to have more ex_data exposed into SSL library later for this. Can we consolidate this with existing SSL_set_app_data by defining a new interface for that purpose?

Copy link
Contributor Author

@jimini-lumox jimini-lumox Dec 16, 2019

Choose a reason for hiding this comment

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

Currently the set_app_data is on the ssl context for ContextImpl, and there exists a set_app_data on the SSL socket in the tls_inspector, so we weren't going to change that.
Because we're using this to be able to provide extra data related to the SSL connection, we've created an SslExtendedSocketInfo class that can be used/extended to pass this information through.
Let me know what you think of this approach (included in the latest commits).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@lizan can you please give this change a re-review when you get a chance, thanks.

Copy link
Member

Choose a reason for hiding this comment

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

Currently the set_app_data is on the ssl context for ContextImpl, and there exists a set_app_data on the SSL socket in the tls_inspector, so we weren't going to change that.
Because we're using this to be able to provide extra data related to the SSL connection, we've created an SslExtendedSocketInfo class that can be used/extended to pass this information through.
Let me know what you think of this approach (included in the latest commits).

The SSL_CTX_set_app_data set ContextImpl which is not in the same scope, and TLS inspector SSL object is not leaked into here.

The only existing SSL_set_app_data is also to provide extra data related to SSL connection for transport socket options here, I meant to refactor these two into one interface and do SSL_set_app_data once.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Could we do this refactor as a subsequent PR - I'm happy to pick this up.
because this may be a bit of a tricky refactor to combine the multiple pieces of info 'cleanly'.
we've got the ContextImpl's const Network::TransportSocketOptions* options being set via SSL_set_app_data by the ContextImpl but only if (options && !options->verifySubjectAltNameListOverride().empty()) when the SslSocket is created,
and then the SslSocketInfo::SslExtendedSocketInfo member being set via SSL_set_ex_data when the SslSocket is subsequently moved to be owned by the constructed SslSocketInfo.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@lizan Can we re-open this PR please - or do we need to create another PR

Copy link
Member

Choose a reason for hiding this comment

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

Could we do this refactor as a subsequent PR - I'm happy to pick this up.
because this may be a bit of a tricky refactor to combine the multiple pieces of info 'cleanly'.
we've got the ContextImpl's const Network::TransportSocketOptions* options being set via SSL_set_app_data by the ContextImpl but only if (options && !options->verifySubjectAltNameListOverride().empty()) when the SslSocket is created,
and then the SslSocketInfo::SslExtendedSocketInfo member being set via SSL_set_ex_data when the SslSocket is subsequently moved to be owned by the constructed SslSocketInfo.

Since this PR is relatively large, so sure, can you file an issue for this and assign yourself?

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, I've created issue: #9867 , but don't appear to have the power to assign myself - can you assign it to me please.

@lizan lizan added the waiting label Dec 4, 2019
@stale
Copy link

stale bot commented Dec 11, 2019

This pull request has been automatically marked as stale because it has not had activity in the last 7 days. It will be closed in 7 days if no further activity occurs. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions!

@stale stale bot added the stale stalebot believes this issue/PR has not been touched recently label Dec 11, 2019
@da77a
Copy link

da77a commented Dec 12, 2019

not stale @jimini-lumox is just offline for a little while. pinging to keep this fresh...

@stale stale bot removed the stale stalebot believes this issue/PR has not been touched recently label Dec 12, 2019
@repokitteh-read-only
Copy link

CC @envoyproxy/api-shepherds: Your approval is needed for changes made to api/.

🐱

Caused by: #9172 was synchronize by jimini-lumox.

see: more, trace.

@stale
Copy link

stale bot commented Dec 25, 2019

This pull request has been automatically marked as stale because it has not had activity in the last 7 days. It will be closed in 7 days if no further activity occurs. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions!

@stale stale bot added stale stalebot believes this issue/PR has not been touched recently and removed stale stalebot believes this issue/PR has not been touched recently labels Dec 25, 2019
@stale
Copy link

stale bot commented Jan 17, 2020

This pull request has been automatically marked as stale because it has not had activity in the last 7 days. It will be closed in 7 days if no further activity occurs. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions!

@stale stale bot added the stale stalebot believes this issue/PR has not been touched recently label Jan 17, 2020
@stale
Copy link

stale bot commented Jan 24, 2020

This pull request has been automatically closed because it has not had activity in the last 14 days. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions!

@stale stale bot closed this Jan 24, 2020
@mattklein123 mattklein123 reopened this Jan 24, 2020
@stale stale bot removed the stale stalebot believes this issue/PR has not been touched recently label Jan 24, 2020
Copy link
Member

@lizan lizan left a comment

Choose a reason for hiding this comment

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

Can you merge master again to fix merge conflicts? Otherwise LGTM once you filed the refactor issue.

@jimini-lumox
Copy link
Contributor Author

Thanks, master merged & built.
Issue: #9867 created for the refactor

Copy link
Member

@lizan lizan left a comment

Choose a reason for hiding this comment

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

Can you also add a line to version_history.rst?

@@ -535,6 +535,7 @@ class TlsContextMatchCriteria {
virtual ~TlsContextMatchCriteria() = default;

virtual const absl::optional<bool>& presented() const PURE;
virtual const absl::optional<bool>& validated() const PURE;
Copy link
Member

Choose a reason for hiding this comment

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

can you add comment to this class and methods?

@@ -6,6 +6,8 @@ Version history
* config: use type URL to select an extension whenever the config type URL (or its previous versions) uniquely identify a typed extension, see :ref:`extension configuration <config_overview_extension_configuration>`.
* retry: added a retry predicate that :ref:`rejects hosts based on metadata. <envoy_api_field_route.RetryPolicy.retry_host_predicate>`
* upstream: changed load distribution algorithm when all priorities enter :ref:`panic mode<arch_overview_load_balancing_panic_threshold>`.
* router: added the ability to match a route based on whether a downstream TLS connection certificate has been
Copy link
Member

Choose a reason for hiding this comment

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

nit: alphabetical order

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@jimini-lumox jimini-lumox force-pushed the feature-untrusted-client-certs branch from 93632da to a0b1c3a Compare January 29, 2020 19:50
Copy link
Member

@lizan lizan left a comment

Choose a reason for hiding this comment

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

Can you fix DCO? Feel free to squash all commit into one and force-push if that's needed.

@jimini-lumox jimini-lumox requested a review from snowp as a code owner January 29, 2020 20:07
lizan
lizan previously approved these changes Jan 30, 2020
@lizan
Copy link
Member

lizan commented Jan 30, 2020

Needs another merge for version_history, thanks!

lizan
lizan previously approved these changes Jan 30, 2020
Copy link
Member

@mattklein123 mattklein123 left a comment

Choose a reason for hiding this comment

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

1 quick API/docs question. Thank you!

/wait

@@ -353,6 +353,9 @@ message RouteMatch {
message TlsContextMatchOptions {
// If specified, the route will match against whether or not a certificate is presented.
google.protobuf.BoolValue presented = 1;

// If specified, the route will match against whether or not a certificate is validated.
Copy link
Member

Choose a reason for hiding this comment

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

What is the default here? Can you clarify?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If not specified, then the validated status (true or false) will not be considered for route matching - it's the same behaviour as the 'presented' field above.

Copy link
Member

Choose a reason for hiding this comment

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

OK can you do me a favor and clarify the docs both here and above that no value means not considered at all, a set value checks that state, etc. Feel free to phrase however you want but it was a bit unclear to me from a quick doc read. Thank you!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've updated it, let me know if it's ok. Thanks.

@jimini-lumox
Copy link
Contributor Author

I seem to have broken a bunch of things when trying to fix the DCO error - and don't think I can recover it in my branch.
Should I create a new PR, with the changes squashed?

@lizan
Copy link
Member

lizan commented Jan 31, 2020

@jimini-lumox if you can squash all into one commit and force push it to same branch it will fix. You don't need another PR but just a force push.

Signed-off-by: Michael Hargreaves <mik.hargreaves@gmail.com>
@jimini-lumox jimini-lumox force-pushed the feature-untrusted-client-certs branch from 378f043 to 928bd25 Compare January 31, 2020 06:00
@jimini-lumox
Copy link
Contributor Author

@lizan I've fixed the DCO issues with a squashed forced push. Thanks

@repokitteh-read-only repokitteh-read-only bot removed the api label Feb 3, 2020
@lizan
Copy link
Member

lizan commented Feb 3, 2020

Defer merge to @mattklein123 for doc check.

@mattklein123 mattklein123 self-assigned this Feb 3, 2020
Copy link
Member

@mattklein123 mattklein123 left a comment

Choose a reason for hiding this comment

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

Thanks!

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.

7 participants