Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.17.1-dev
1.17.1
5 changes: 3 additions & 2 deletions docs/root/version_history/current.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
1.17.1 (Pending)
================
1.17.1 (February 25, 2021)
==========================

Incompatible Behavior Changes
-----------------------------
Expand All @@ -13,6 +13,7 @@ Bug Fixes
---------
*Changes expected to improve the state of the world and are unlikely to have negative effects*

* jwt_authn: reject requests with a proper error if JWT has the wrong issuer when allow_missing is used. Before this change, the requests are accepted.
* overload: fix a bug that can cause use-after-free when one scaled timer disables another one with the same duration.

Removed Config or Runtime
Expand Down
15 changes: 7 additions & 8 deletions source/extensions/filters/http/jwt_authn/verifier.cc
Original file line number Diff line number Diff line change
Expand Up @@ -301,17 +301,16 @@ class AnyVerifierImpl : public BaseGroupVerifierImpl {
// Then wait for all children to be done.
if (++completion_state.number_completed_children_ == verifiers_.size()) {
// Aggregate all children status into a final status.
// JwtMissing should be treated differently than other failure status
// since it simply means there is not Jwt token for the required provider.
// If there is a failure status other than JwtMissing in the children,
// it should be used as the final status.
// JwtMissed and JwtUnknownIssuer should be treated differently than other errors.
// JwtMissed means not Jwt token for the required provider.
// JwtUnknownIssuer means wrong issuer for the required provider.
Status final_status = Status::JwtMissed;
for (const auto& it : verifiers_) {
// If a Jwt is extracted from a location not specified by the required provider,
// the authenticator returns JwtUnknownIssuer. It should be treated the same as
// JwtMissed.
// Prefer errors which are not JwtMissed nor JwtUnknownIssuer.
// Prefer JwtUnknownIssuer between JwtMissed and JwtUnknownIssuer.
Status child_status = context.getCompletionState(it.get()).status_;
if (child_status != Status::JwtMissed && child_status != Status::JwtUnknownIssuer) {
if ((child_status != Status::JwtMissed && child_status != Status::JwtUnknownIssuer) ||
final_status == Status::JwtMissed) {
final_status = child_status;
}
}
Expand Down
13 changes: 11 additions & 2 deletions test/extensions/filters/http/jwt_authn/all_verifier_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ TEST_F(SingleAllowMissingInOrListTest, BadJwt) {
}

TEST_F(SingleAllowMissingInOrListTest, MissingIssToken) {
EXPECT_CALL(mock_cb_, onComplete(Status::Ok));
EXPECT_CALL(mock_cb_, onComplete(Status::JwtUnknownIssuer));
auto headers = Http::TestRequestHeaderMapImpl{{kExampleHeader, ES256WithoutIssToken}};
context_ = Verifier::createContext(headers, parent_span_, &mock_cb_);
verifier_->verify(context_);
Expand Down Expand Up @@ -471,6 +471,15 @@ TEST_F(AllowMissingInOrListTest, OtherGoodJwt) {
EXPECT_THAT(headers, JwtOutputFailedOrIgnore(kOtherHeader));
}

TEST_F(AllowMissingInOrListTest, WrongIssuer) {
EXPECT_CALL(mock_cb_, onComplete(Status::JwtUnknownIssuer));
auto headers = Http::TestRequestHeaderMapImpl{{kExampleHeader, OtherGoodToken}};
context_ = Verifier::createContext(headers, parent_span_, &mock_cb_);
verifier_->verify(context_);
// x-other JWT should be ignored.
EXPECT_THAT(headers, JwtOutputFailedOrIgnore(kOtherHeader));
}

TEST_F(AllowMissingInOrListTest, BadAndGoodJwts) {
EXPECT_CALL(mock_cb_, onComplete(Status::JwtVerificationFail));
auto headers = Http::TestRequestHeaderMapImpl{{kExampleHeader, NonExistKidToken},
Expand Down Expand Up @@ -589,7 +598,7 @@ TEST_F(AllowMissingInAndOfOrListTest, TwoGoodJwts) {
}

TEST_F(AllowMissingInAndOfOrListTest, GoodAndBadJwts) {
EXPECT_CALL(mock_cb_, onComplete(Status::Ok));
EXPECT_CALL(mock_cb_, onComplete(Status::JwtUnknownIssuer));
// Use the token with example.com issuer for x-other.
auto headers =
Http::TestRequestHeaderMapImpl{{kExampleHeader, GoodToken}, {kOtherHeader, GoodToken}};
Expand Down
6 changes: 3 additions & 3 deletions test/extensions/filters/http/jwt_authn/group_verifier_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -582,8 +582,8 @@ TEST_F(GroupVerifierTest, TestRequiresAnyWithAllowMissingButFailed) {
callbacks_["other_provider"](Status::JwtExpired);
}

// Test RequiresAny with two providers and allow_missing, but OK
TEST_F(GroupVerifierTest, TestRequiresAnyWithAllowMissingButOk) {
// Test RequiresAny with two providers and allow_missing, but one returns JwtUnknownIssuer
TEST_F(GroupVerifierTest, TestRequiresAnyWithAllowMissingButUnknownIssuer) {
TestUtility::loadFromYaml(RequiresAnyConfig, proto_config_);
proto_config_.mutable_rules(0)
->mutable_requires()
Expand All @@ -592,7 +592,7 @@ TEST_F(GroupVerifierTest, TestRequiresAnyWithAllowMissingButOk) {
->mutable_allow_missing();

createAsyncMockAuthsAndVerifier(std::vector<std::string>{"example_provider", "other_provider"});
EXPECT_CALL(mock_cb_, onComplete(Status::Ok));
EXPECT_CALL(mock_cb_, onComplete(Status::JwtUnknownIssuer));

auto headers = Http::TestRequestHeaderMapImpl{};
context_ = Verifier::createContext(headers, parent_span_, &mock_cb_);
Expand Down