Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
4bf0213
Add Jwt cache.
Dec 9, 2020
07e3923
Fixed comments and updated config proto.
Dec 13, 2020
e89cf2c
Suppressed unused parameter.
Dec 13, 2020
6c5e822
Fixed CI.
Dec 13, 2020
23d6b6b
Merge remote-tracking branch 'upstream/master' into jwt-cache
Dec 14, 2020
0d70dd7
Updated jwt_verify_lib release.
Dec 17, 2020
433e4c8
Merge remote-tracking branch 'upstream/master' into jwt-cache
Dec 23, 2020
35383c3
Resolved comments.
Dec 25, 2020
4d92197
Added token_cache_size.
Jan 8, 2021
6d9cbac
Updated config for JwtProvider
Feb 2, 2021
4d27b57
Fixed comments.
Feb 18, 2021
742220e
Fix.
Feb 25, 2021
883de98
Merge remote-tracking branch 'upstream/main' into jwt-cache
Mar 1, 2021
ac891a6
Fixed CI.
Mar 2, 2021
d69df58
Fix comments.
Mar 3, 2021
eacfbc3
Fixed release call.
Mar 4, 2021
1335cf6
Fixed memory release.
Mar 5, 2021
c8efe0e
Fixed windows CI.
Mar 5, 2021
9875c74
Fixed release metadata.
Mar 24, 2021
26b94cb
Redesigned Jwt Cache.
Mar 24, 2021
11e4057
fix
Mar 24, 2021
1f36422
fix
Mar 25, 2021
8964983
fix
Mar 25, 2021
8a3cb9c
fix
Mar 26, 2021
a2a31e5
fix.
Mar 31, 2021
a52ec67
Merge remote-tracking branch 'upstream/main' into jwt-cache
Mar 31, 2021
bb42b8d
Added release docs.
Apr 1, 2021
04335c7
fix
Apr 1, 2021
cfcd530
fix docs warning
Apr 1, 2021
f33850d
fix clang-tidy
Apr 1, 2021
e11c695
Update tests
qiwzhang Apr 20, 2021
c18856c
Merge remote-tracking branch 'upstream/main' into jwt-cache
Apr 20, 2021
b986895
fix docs.
Apr 20, 2021
3460ec0
fix format
Apr 20, 2021
ef3ad74
fix clang-tidy
Apr 20, 2021
3b95eee
Moved JwtCache in ThreadLocalCache
Apr 26, 2021
ca3cbee
fix
Apr 26, 2021
3d47511
fix
Apr 26, 2021
e13209e
Merge branch 'main' into jwt-cache
Apr 27, 2021
b96dc33
Merge remote-tracking branch 'upstream/main' into jwt-cache
Apr 27, 2021
8a175d5
fix
May 6, 2021
9419ddf
Merge remote-tracking branch 'upstream/main' into jwt-cache
May 6, 2021
7ac42c0
Merge branch 'main' into jwt-cache
May 20, 2021
07d45bb
Merge branch 'main' into jwt-cache
May 27, 2021
d0e83f2
Removed new line.
May 27, 2021
3f7c0c4
Resolved merge conflict.
Jun 1, 2021
45d3132
fixed CI.
Jun 1, 2021
13cb2b5
Merge remote-tracking branch 'upstream/main' into jwt-cache
Jun 7, 2021
f5fb8a4
fixed CI.
Jun 7, 2021
3e7768d
fix
Jun 9, 2021
17fe231
fix api docs
Jun 16, 2021
5372efd
Added 4KiB limit for JWT size
Jun 16, 2021
a1d3c72
fix style.
Jun 16, 2021
4f7caeb
Added JwtCacheConfig.
Jun 21, 2021
e4ceaac
Improve api
Jun 21, 2021
783c207
Merge remote-tracking branch 'upstream/main' into jwt-cache
Jun 28, 2021
a583ba7
fix
Jun 28, 2021
1de642f
Merge branch 'main' into jwt-cache
Jul 14, 2021
45f7298
fix rst
Jul 14, 2021
fd2f636
fix protos
Jul 14, 2021
a23bf86
fix test
Jul 14, 2021
4989b45
fix
Jul 15, 2021
25f366a
Merge remote-tracking branch 'upstream/main' into jwt-cache
Jul 15, 2021
efb4bb6
fix
Jul 15, 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
17 changes: 8 additions & 9 deletions source/extensions/filters/http/jwt_authn/authenticator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class AuthenticatorImpl : public Logger::Loggable<Logger::Id::jwt>,
public:
AuthenticatorImpl(const CheckAudience* check_audience,
const absl::optional<std::string>& provider, bool allow_failed,
bool allow_missing, JwksCache& jwks_cache,
bool allow_missing, Cache& jwks_cache,
Upstream::ClusterManager& cluster_manager,
CreateJwksFetcherCb create_jwks_fetcher_cb, TimeSource& time_source)
: jwks_cache_(jwks_cache), cm_(cluster_manager),
Expand Down Expand Up @@ -65,7 +65,7 @@ class AuthenticatorImpl : public Logger::Loggable<Logger::Id::jwt>,
void startVerify();

// The jwks cache object.
JwksCache& jwks_cache_;
Cache& jwks_cache_;
// the cluster manager object.
Upstream::ClusterManager& cm_;

Expand All @@ -81,8 +81,7 @@ class AuthenticatorImpl : public Logger::Loggable<Logger::Id::jwt>,
// The JWT object.
std::unique_ptr<::google::jwt_verify::Jwt> jwt_;
// The JWKS data object
JwksCache::JwksData* jwks_data_{};

Cache::JwksData* jwks_data_{};
// The HTTP request headers
Http::HeaderMap* headers_{};
// The active span for the request
Expand Down Expand Up @@ -141,9 +140,9 @@ void AuthenticatorImpl::startVerify() {

jwt_ = std::make_unique<::google::jwt_verify::Jwt>();
ENVOY_LOG(debug, "{}: Parse Jwt {}", name(), curr_token_->token());
Status status = jwt_->parseFromString(curr_token_->token());
if (status != Status::Ok) {
doneWithStatus(status);
jwks_data_->addTokenResult(curr_token_->token(), *jwt_);
if (jwks_data_->getJwtStatus() != Status::Ok) {
doneWithStatus(jwks_data_->getJwtStatus());
return;
}

Expand Down Expand Up @@ -174,7 +173,7 @@ void AuthenticatorImpl::startVerify() {
if (jwks_data_->getJwtProvider().clock_skew_seconds() > 0) {
clock_skew_seconds = jwks_data_->getJwtProvider().clock_skew_seconds();
}
status = jwt_->verifyTimeConstraint(absl::ToUnixSeconds(absl::Now()), clock_skew_seconds);
Status status = jwt_->verifyTimeConstraint(absl::ToUnixSeconds(absl::Now()), clock_skew_seconds);
Comment thread
mk46 marked this conversation as resolved.
Outdated
if (status != Status::Ok) {
doneWithStatus(status);
return;
Expand Down Expand Up @@ -293,7 +292,7 @@ void AuthenticatorImpl::doneWithStatus(const Status& status) {

AuthenticatorPtr Authenticator::create(const CheckAudience* check_audience,
const absl::optional<std::string>& provider,
bool allow_failed, bool allow_missing, JwksCache& jwks_cache,
bool allow_failed, bool allow_missing, Cache& jwks_cache,
Upstream::ClusterManager& cluster_manager,
CreateJwksFetcherCb create_jwks_fetcher_cb,
TimeSource& time_source) {
Expand Down
2 changes: 1 addition & 1 deletion source/extensions/filters/http/jwt_authn/authenticator.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class Authenticator {
// Authenticator factory function.
static AuthenticatorPtr create(const ::google::jwt_verify::CheckAudience* check_audience,
const absl::optional<std::string>& provider, bool allow_failed,
bool allow_missing, JwksCache& jwks_cache,
bool allow_missing, Cache& jwks_cache,
Upstream::ClusterManager& cluster_manager,
CreateJwksFetcherCb create_jwks_fetcher_cb,
TimeSource& time_source);
Expand Down
10 changes: 5 additions & 5 deletions source/extensions/filters/http/jwt_authn/filter_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ class ThreadLocalCache : public ThreadLocal::ThreadLocalObject {
// Load the config from envoy config.
ThreadLocalCache(const envoy::extensions::filters::http::jwt_authn::v3::JwtAuthentication& config,
TimeSource& time_source, Api::Api& api) {
jwks_cache_ = JwksCache::create(config, time_source, api);
jwks_cache_ = Cache::create(config, time_source, api);
}

// Get the JwksCache object.
JwksCache& getJwksCache() { return *jwks_cache_; }
// Get the Cache object.
Cache& getJwksCache() { return *jwks_cache_; }

private:
// The JwksCache object.
JwksCachePtr jwks_cache_;
// The Cache object.
CachePtr jwks_cache_;
};

/**
Expand Down
35 changes: 29 additions & 6 deletions source/extensions/filters/http/jwt_authn/jwks_cache.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include "extensions/filters/http/jwt_authn/jwks_cache.h"

#include <chrono>
#include <memory>
#include <string>

#include "envoy/common/time.h"
#include "envoy/extensions/filters/http/jwt_authn/v3/config.pb.h"
Expand All @@ -26,7 +28,7 @@ namespace {
// Default cache expiration time in 5 minutes.
constexpr int PubkeyCacheExpirationSec = 600;

class JwksDataImpl : public JwksCache::JwksData, public Logger::Loggable<Logger::Id::jwt> {
class JwksDataImpl : public Cache::JwksData, public Logger::Loggable<Logger::Id::jwt> {
public:
JwksDataImpl(const JwtProvider& jwt_provider, TimeSource& time_source, Api::Api& api)
: jwt_provider_(jwt_provider), time_source_(time_source) {
Expand Down Expand Up @@ -63,6 +65,23 @@ class JwksDataImpl : public JwksCache::JwksData, public Logger::Loggable<Logger:
return setKey(std::move(jwks), getRemoteJwksExpirationTime());
}

Status getJwtStatus() override { return jwt_status_; }

void addTokenResult(const std::string& token, ::google::jwt_verify::Jwt& token_result) override {
jwt_status_ = token_result.parseFromString(token);
if (jwt_status_ == Status::Ok) {
jwt_ = std::make_unique<::google::jwt_verify::Jwt>(token_result);
}
}

bool findTokenResult(const std::string& token, ::google::jwt_verify::Jwt& token_result) override {
Status status = token_result.parseFromString(token);
if (status != Status::Ok) {
return false;
}
return true;
}

private:
// Get the expiration time for a remote Jwks
std::chrono::steady_clock::time_point getRemoteJwksExpirationTime() const {
Expand Down Expand Up @@ -92,9 +111,13 @@ class JwksDataImpl : public JwksCache::JwksData, public Logger::Loggable<Logger:
TimeSource& time_source_;
// The pubkey expiration time.
MonotonicTime expiration_time_;
// Jwt object for verified token.
std::unique_ptr<::google::jwt_verify::Jwt> jwt_;

@qiwzhang qiwzhang Dec 9, 2020

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.

The cache should be:


// Map a token to its result in the cache
absl::flat_hash_map<string,  TokenResult> token_cache_;

Struct TokenResult {
     // cache expire time, default cache for 5 minutes
     MonotonicTime expiration_time_;
     // verification status
     Status  status_;
}

In the jwt_authn config, in the JwtProvider config, add

   // enable cache 
   bool enable_token_cache ;

  // specify token cache during,  default to 5 minutes
   Duration  token_cache_duration;

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.

should the cache have a (optionally) limited size to cap the amount of memory it can use?

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.

ahh nvm, i saw you commented on that.

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.

// A valid error on parsing Jwt.
Status jwt_status_;
};

class JwksCacheImpl : public JwksCache {
class JwksCacheImpl : public Cache {
public:
// Load the config from envoy config.
JwksCacheImpl(const JwtAuthentication& config, TimeSource& time_source, Api::Api& api) {
Expand Down Expand Up @@ -132,10 +155,10 @@ class JwksCacheImpl : public JwksCache {

} // namespace

JwksCachePtr
JwksCache::create(const envoy::extensions::filters::http::jwt_authn::v3::JwtAuthentication& config,
TimeSource& time_source, Api::Api& api) {
return JwksCachePtr(new JwksCacheImpl(config, time_source, api));
CachePtr
Cache::create(const envoy::extensions::filters::http::jwt_authn::v3::JwtAuthentication& config,
TimeSource& time_source, Api::Api& api) {
return CachePtr(new JwksCacheImpl(config, time_source, api));
}

} // namespace JwtAuthn
Expand Down
21 changes: 16 additions & 5 deletions source/extensions/filters/http/jwt_authn/jwks_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@
#include "envoy/extensions/filters/http/jwt_authn/v3/config.pb.h"

#include "jwt_verify_lib/jwks.h"
#include "jwt_verify_lib/jwt.h"

namespace Envoy {
namespace Extensions {
namespace HttpFilters {
namespace JwtAuthn {

class JwksCache;
using JwksCachePtr = std::unique_ptr<JwksCache>;
using ::google::jwt_verify::Status;

class Cache;
using CachePtr = std::unique_ptr<Cache>;

/**
* Interface to access all configured Jwt rules and their cached Jwks objects.
Expand All @@ -33,9 +36,9 @@ using JwksCachePtr = std::unique_ptr<JwksCache>;
* verifyJwt(jwks_data->getJwksObj(), jwt);
*/

class JwksCache {
class Cache {
Comment thread
mk46 marked this conversation as resolved.
Outdated
public:
virtual ~JwksCache() = default;
virtual ~Cache() = default;

// Interface to access a Jwks config rule and its cached Jwks object.
class JwksData {
Expand All @@ -58,6 +61,14 @@ class JwksCache {
// Set a remote Jwks.
virtual const ::google::jwt_verify::Jwks*
setRemoteJwks(::google::jwt_verify::JwksPtr&& jwks) PURE;

virtual Status getJwtStatus() PURE;

virtual void addTokenResult(const std::string& token,
::google::jwt_verify::Jwt& token_result) PURE;

virtual bool findTokenResult(const std::string& token,
::google::jwt_verify::Jwt& token_result) PURE;
};

// Lookup issuer cache map. The cache only stores Jwks specified in the config.
Expand All @@ -66,7 +77,7 @@ class JwksCache {
virtual JwksData* findByProvider(const std::string& provider) PURE;

// Factory function to create an instance.
static JwksCachePtr
static CachePtr
create(const envoy::extensions::filters::http::jwt_authn::v3::JwtAuthentication& config,
TimeSource& time_source, Api::Api& api);
};
Expand Down
12 changes: 6 additions & 6 deletions test/extensions/filters/http/jwt_authn/jwks_cache_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ class JwksCacheTest : public testing::Test {
JwksCacheTest() : api_(Api::createApiForTest()) {}
void SetUp() override {
TestUtility::loadFromYaml(ExampleConfig, config_);
cache_ = JwksCache::create(config_, time_system_, *api_);
cache_ = Cache::create(config_, time_system_, *api_);
jwks_ = google::jwt_verify::Jwks::createFrom(PublicKey, google::jwt_verify::Jwks::JWKS);
}

Event::SimulatedTimeSystem time_system_;
JwtAuthentication config_;
JwksCachePtr cache_;
CachePtr cache_;
google::jwt_verify::JwksPtr jwks_;
Api::ApiPtr api_;
};
Expand All @@ -48,7 +48,7 @@ TEST_F(JwksCacheTest, TestSetRemoteJwks) {
auto& provider0 = (*config_.mutable_providers())[std::string(ProviderName)];
// Set cache_duration to 1 second to test expiration
provider0.mutable_remote_jwks()->mutable_cache_duration()->set_seconds(1);
cache_ = JwksCache::create(config_, time_system_, *api_);
cache_ = Cache::create(config_, time_system_, *api_);

auto jwks = cache_->findByIssuer("https://example.com");
EXPECT_TRUE(jwks->getJwksObj() == nullptr);
Expand All @@ -67,7 +67,7 @@ TEST_F(JwksCacheTest, TestSetRemoteJwksWithDefaultCacheDuration) {
auto& provider0 = (*config_.mutable_providers())[std::string(ProviderName)];
// Clear cache_duration to use default one.
provider0.mutable_remote_jwks()->clear_cache_duration();
cache_ = JwksCache::create(config_, time_system_, *api_);
cache_ = Cache::create(config_, time_system_, *api_);

auto jwks = cache_->findByIssuer("https://example.com");
EXPECT_TRUE(jwks->getJwksObj() == nullptr);
Expand All @@ -84,7 +84,7 @@ TEST_F(JwksCacheTest, TestGoodInlineJwks) {
auto local_jwks = provider0.mutable_local_jwks();
local_jwks->set_inline_string(PublicKey);

cache_ = JwksCache::create(config_, time_system_, *api_);
cache_ = Cache::create(config_, time_system_, *api_);

auto jwks = cache_->findByIssuer("https://example.com");
EXPECT_FALSE(jwks->getJwksObj() == nullptr);
Expand All @@ -98,7 +98,7 @@ TEST_F(JwksCacheTest, TestBadInlineJwks) {
auto local_jwks = provider0.mutable_local_jwks();
local_jwks->set_inline_string("BAD-JWKS");

cache_ = JwksCache::create(config_, time_system_, *api_);
cache_ = Cache::create(config_, time_system_, *api_);

auto jwks = cache_->findByIssuer("https://example.com");
EXPECT_TRUE(jwks->getJwksObj() == nullptr);
Expand Down