Creating JwksFetcher interface and impl v2#4242
Creating JwksFetcher interface and impl v2#4242htuch merged 23 commits intoenvoyproxy:masterfrom thales-e-security:master
Conversation
JwksFetcher wraps up HTTP acquisition of JWKS strings converting them into a concrete type on the way. JwksFetcher is reusable so can be used in a wider context. Tests updated and fixed where necessary. Signed-off-by: Nick A. Smith <nick.a.smith@thales-esecurity.com>
- Changes from PR review. - Added missing tests for JwksFetcher::cancel(). - Added comment and TODO around a potential bug in jwt_authn::authenticator. Signed-off-by: Nick A. Smith <nick.a.smith@thales-esecurity.com>
| return; | ||
| } | ||
|
|
||
| // TODO: Cross-platform-wise the below unix_timestamp code is wrong as the |
| if (jwks_data_->getJwksObj() != nullptr && !jwks_data_->isExpired()) { | ||
| auto jwks_obj = jwks_data_->getJwksObj(); | ||
| if (jwks_obj != nullptr && !jwks_data_->isExpired()) { | ||
| // TODO: It would seem there's a window of error whereby if the JWT issuer |
There was a problem hiding this comment.
@qiwzhang note the comment I've added here.
There was a problem hiding this comment.
Can you assign a TODO owner, e.g. TODO(nickrmc83)?
Signed-off-by: Nick A. Smith <nick.a.smith@thales-esecurity.com>
| @@ -3,7 +3,7 @@ | |||
| namespace Envoy { | |||
| namespace Extensions { | |||
| namespace HttpFilters { | |||
| namespace JwtAuthn { | |||
There was a problem hiding this comment.
It seems that data are still specific to jwt_authn. so the file name is still better call "jwt_authn_common"
There was a problem hiding this comment.
My thinking here was that all JWT related test vectors should reside together especially as they all use the same signing keys. Happy to move if necessary but some of the variables are used in the jwks_fetcher_test
qiwzhang
left a comment
There was a problem hiding this comment.
Looks pretty good. Only some small comments.
|
LGTM |
- Removed unused response_message variable - use of std::make_unique - Fix enum inline with style guide - Added missing param documentation - Added comments re: nbf and exp JWT fields and their default values - Used reference instead of pointer for non-null function param Signed-off-by: Nick A. Smith <nick.a.smith@thales-esecurity.com>
Signed-off-by: Nick A. Smith <nick.a.smith@thales-esecurity.com>
| @@ -3,7 +3,7 @@ | |||
| namespace Envoy { | |||
| namespace Extensions { | |||
| namespace HttpFilters { | |||
| namespace JwtAuthn { | |||
The most major change is to swap JwksFetcher creation to be just-in-time using a lambda callback. Moved test_common.h from test/extensions/filters/http/common back to test/extensions/filters/http/jwt_authn. Most others changes are minor. Signed-off-by: Nick A. Smith <nick.a.smith@thales-esecurity.com>
|
@qiwzhang @lizan I think this is now done with all nits picked. There are some outstanding comments from me that I'd like either of you to resolve specifically regarding the comments I've added to the code for potential areas to be addressed as well as an explanation about why there's a new abseil dependency. |
lizan
left a comment
There was a problem hiding this comment.
LGTM modulo one comment, thanks!
Signed-off-by: Nick A. Smith <nick.a.smith@thales-esecurity.com>
|
fix format? |
Signed-off-by: Nick A. Smith <nick.a.smith@thales-esecurity.com>
Signed-off-by: Nick A. Smith <nick.a.smith@thales-esecurity.com>
bazel/repositories.bzl
Outdated
| @@ -465,8 +465,8 @@ def _com_google_absl(): | |||
| actual = "@com_google_absl//absl/debugging:symbolize", | |||
| ) | |||
|
|
|||
There was a problem hiding this comment.
run tools/check_format.py fix, it is complaining about trailing whitespace on this line.
Check_format.py made some unwanted changes to certain lines in baxel/repositories.bzl that had not been modified. I've reverted those lines in the hope they will take. Signed-off-by: Nick A. Smith <nick.a.smith@thales-esecurity.com>
|
|
||
| void fetch(const ::envoy::api::v2::core::HttpUri& uri, JwksFetcher::JwksReceiver& receiver) { | ||
| ENVOY_LOG(trace, "{}", __func__); | ||
| receiver_ = &receiver; |
There was a problem hiding this comment.
What if receiver_ is already set? What is the contract on multiple fetches?
There was a problem hiding this comment.
@htuch There's a description of the use of the Jwksetcher interface just before the definition in the header file. Would you like further commentary closer to the fetch() method?
Just seen your later comment :)
There was a problem hiding this comment.
Can you ASSERT here that recever_ == nullptr, i.e. we catch in debug builds violations of the contract.
| /** | ||
| * JwksFetcher interface can be used to retrieve remote JWKS | ||
| * (https://tools.ietf.org/html/rfc7517) data structures returning a concrete, | ||
| * type-safe representation. An instance of this interface is designed to |
There was a problem hiding this comment.
Ah, you answer the above question here. This is a pretty weird pattern; I would call it out by explicitly naming the class/interface JwksSingleUseFetcher or something like that.
Mainly small fixes and better documentation. Signed-off-by: Nick A. Smith <nick.a.smith@thales-esecurity.com>
htuch
left a comment
There was a problem hiding this comment.
Looks good! Just a few more comments and this should be ready to go.
| virtual void cancel() PURE; | ||
|
|
||
| /* | ||
| * Retrieve a JWKS resource from a remote HTTP host. |
There was a problem hiding this comment.
Retrieve a JWKS resource from a remote HTTP host. At most one outstanding request may be in-flight, i.e. from the invocation of `fetch()` until either a callback or `cancel()` is invoked, no additional `fetch()` may be issued.
| class JwksReceiver { | ||
| public: | ||
| enum class Failure { | ||
| Unknown, |
There was a problem hiding this comment.
Please comment these reason values.
|
|
||
| void fetch(const ::envoy::api::v2::core::HttpUri& uri, JwksFetcher::JwksReceiver& receiver) { | ||
| ENVOY_LOG(trace, "{}", __func__); | ||
| receiver_ = &receiver; |
There was a problem hiding this comment.
Can you ASSERT here that recever_ == nullptr, i.e. we catch in debug builds violations of the contract.
| } | ||
| // If the exp claim does *not* appear in the JWT then the exp field is defaulted | ||
| // to 0. | ||
| if (jwt_.exp_ && jwt_.exp_ < unix_timestamp) { |
There was a problem hiding this comment.
Prefer maintaining jwt_.exp_ > 0 as before for clarity.
| if (jwks_data_->getJwksObj() != nullptr && !jwks_data_->isExpired()) { | ||
| auto jwks_obj = jwks_data_->getJwksObj(); | ||
| if (jwks_obj != nullptr && !jwks_data_->isExpired()) { | ||
| // TODO: It would seem there's a window of error whereby if the JWT issuer |
There was a problem hiding this comment.
Can you assign a TODO owner, e.g. TODO(nickrmc83)?
Changes from final PR review to include missing unit testand fix commenting Signed-off-by: Nick A. Smith <nick.a.smith@thales-esecurity.com>
Signed-off-by: Nick A. Smith <nick.a.smith@thales-esecurity.com>
Signed-off-by: Nick A. Smith <nick.a.smith@thales-esecurity.com>
This should fix any use-after-free errors Signed-off-by: Nick A. Smith <nick.a.smith@thales-esecurity.com>
|
@nickrmc83 is this now ready for another pass? I.e. coverage fixed etc. |
|
@htuch This is now ready. |
htuch
left a comment
There was a problem hiding this comment.
LGTM, thanks! One last tiny nit and we can ship.
| * Expectations and assertions should be made on onJwksSuccessImpl in place | ||
| * of onJwksSuccess. | ||
| */ | ||
| void onJwksSuccess(google::jwt_verify::JwksPtr&& jwks) { onJwksSuccessImpl(jwks); } |
There was a problem hiding this comment.
Nit: can you change this to pass Jwks& and deref the unique_ptr in args? In general, it doesn't make a lot of sense to pass unique_ptr by ref.
There was a problem hiding this comment.
I've changed onJwksSuccessImpl to receive a const Jwks* to avoid the unique_ptr pass-by-reference.
We now pass by const ptr. Signed-off-by: Nick A. Smith <nick.a.smith@thales-esecurity.com>
htuch
left a comment
There was a problem hiding this comment.
Needs to merge master to resolve a conflict.
Signed-off-by: Nick A. Smith <nick.a.smith@thales-esecurity.com>
Signed-off-by: Nick A. Smith <nick.a.smith@thales-esecurity.com>
Signed-off-by: Nick A. Smith <nick.a.smith@thales-esecurity.com>
|
LGTM |
Signed-off-by: Nick A. Smith <nick.a.smith@thales-esecurity.com>
Signed-off-by: Nick A. Smith <nick.a.smith@thales-esecurity.com>
|
@htuch I think this is done with the following caveats
Can you advise on the format error? |
|
@nickrmc83 are you using check_format outside of Docker? If so, maybe you have a version mismatch? Ideally you just run |
Signed-off-by: Nick A. Smith <nick.a.smith@thales-esecurity.com>
JwksFetcher wraps up HTTP acquisition of JWKS strings converting them into a concrete type on the way.
JwksFetcher is reusable so can be used in a wider context.
Tests updated and fixed where necessary.
Description:
We are in the process of implementing a new Envoy filter based on the design presented here and wish to re-use existing logic in the jwt_authn filter. We've split out the logic we're interested in into a new class called JwksFetcher. Later PRs will re-use the split out logic an OpenID Connect filter.
This is the second crack at this PR (see #4225 which went horribly wrong after following the DCO rebase guidelines).
Risk Level:
Medium
Testing:
Add replacement and additional unit tests for the logic that's been moved.
Docs Changes:
None
Release Notes:
[Optional Fixes #Issue]
[Optional Deprecated:]