Skip to content
Closed
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
149 changes: 149 additions & 0 deletions extensions/authn/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
# Copyright 2018 Istio Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
################################################################################
#

package(default_visibility = ["//visibility:public"])

load(
"@envoy//bazel:envoy_build_system.bzl",
"envoy_cc_library",
"envoy_cc_test",
"envoy_cc_test_library",
)

envoy_cc_library(
name = "authenticator_essential_lib",
srcs = [
"authn_utils.cc",
"connection_context.cc",
"filter_context.cc",
],
hdrs = [
"authn_utils.h",
"connection_context.h",
"filter_context.h",
],
repository = "@envoy",
visibility = ["//visibility:public"],
deps = [
"//extensions/common:json_util",
"//external:security_authentication_config_cc_proto",
"//src/envoy/utils:filter_names_lib",
"//src/envoy/utils:utils_lib",
"//src/istio/authn:context_proto_cc_proto",
"@envoy//source/common/http:headers_lib",
"@envoy//source/exe:envoy_common_lib",
],
)

envoy_cc_library(
name = "request_authenticator_lib",
srcs = [
"request_authenticator.cc",
],
hdrs = [
"request_authenticator.h",
],
repository = "@envoy",
visibility = ["//visibility:public"],
deps = [
":authenticator_essential_lib",
],
)

envoy_cc_library(
name = "peer_authenticator_lib",
srcs = [
"peer_authenticator.cc",
],
hdrs = [
"peer_authenticator.h",
],
repository = "@envoy",
visibility = ["//visibility:public"],
deps = [
":authenticator_essential_lib",
],
)

envoy_cc_test_library(
name = "test_utils",
hdrs = ["test_utils.h"],
repository = "@envoy",
deps = [
"//src/istio/authn:context_proto_cc_proto",
],
)

envoy_cc_test(
name = "request_authenticator_test",
srcs = ["request_authenticator_test.cc"],
repository = "@envoy",
deps = [
":request_authenticator_lib",
":test_utils",
"@envoy//test/mocks/http:http_mocks",
"@envoy//test/test_common:utility_lib",
],
)

envoy_cc_test(
name = "connection_context_test",
srcs = ["connection_context_test.cc"],
repository = "@envoy",
deps = [
":request_authenticator_lib",
":test_utils",
"@envoy//test/mocks/network:network_mocks",
"@envoy//test/mocks/ssl:ssl_mocks",
"@envoy//test/test_common:utility_lib",
],
)

envoy_cc_test(
name = "peer_authenticator_test",
srcs = ["peer_authenticator_test.cc"],
repository = "@envoy",
deps = [
":peer_authenticator_lib",
":test_utils",
"@envoy//test/mocks/http:http_mocks",
"@envoy//test/test_common:utility_lib",
],
)

envoy_cc_test(
name = "filter_context_test",
srcs = ["filter_context_test.cc"],
repository = "@envoy",
deps = [
":authenticator_essential_lib",
":test_utils",
"@envoy//test/mocks/http:http_mocks",
"@envoy//test/test_common:utility_lib",
],
)

envoy_cc_test(
name = "authn_utils_test",
srcs = ["authn_utils_test.cc"],
repository = "@envoy",
deps = [
":authenticator_essential_lib",
":test_utils",
"@envoy//test/test_common:utility_lib",
],
)
125 changes: 125 additions & 0 deletions extensions/authn/authn_utils.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/* Copyright 2020 Istio Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "authn_utils.h"

#include <regex>

#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_split.h"
#include "extensions/common/json_util.h"
#include "google/protobuf/struct.pb.h"

namespace Extensions {
namespace AuthN {
namespace {
// The JWT audience key name
static const std::string kJwtAudienceKey = "aud";
// The JWT issuer key name
static const std::string kJwtIssuerKey = "iss";
// The key name for the original claims in an exchanged token
static const std::string kExchangedTokenOriginalPayload = "original_claims";

}; // namespace

bool AuthnUtils::ProcessJwtPayload(const std::string& payload_str,
istio::authn::JwtPayload* payload) {
auto result = Wasm::Common::JsonParse(payload_str);
if (!result.has_value()) {
return false;
}
auto json_obj = result.value();

*payload->mutable_raw_claims() = payload_str;

auto claims = payload->mutable_claims()->mutable_fields();
// Extract claims as string lists
Wasm::Common::JsonObjectIterate(
json_obj, [&json_obj, &claims](const std::string& key) -> bool {
// In current implementation, only string/string list objects are
// extracted
std::vector<absl::string_view> list;
auto field_value =
Wasm::Common::JsonGetField<std::vector<absl::string_view>>(json_obj,
key);
if (field_value.detail() != Wasm::Common::JsonParserResultDetail::OK) {
auto str_field_value =
Wasm::Common::JsonGetField<absl::string_view>(json_obj, key);
if (str_field_value.detail() !=
Wasm::Common::JsonParserResultDetail::OK) {
return true;
}
list = absl::StrSplit(str_field_value.value().data(), ' ',
absl::SkipEmpty());
} else {
list = field_value.value();
}
for (auto& s : list) {
(*claims)[key].mutable_list_value()->add_values()->set_string_value(
std::string(s));
}
return true;
});

// Copy audience to the audience in context.proto
if (claims->find(kJwtAudienceKey) != claims->end()) {
for (const auto& v : (*claims)[kJwtAudienceKey].list_value().values()) {
payload->add_audiences(v.string_value());
}
}

// Build user
if (claims->find("iss") != claims->end() &&
claims->find("sub") != claims->end()) {
payload->set_user(
(*claims)["iss"].list_value().values().Get(0).string_value() + "/" +
(*claims)["sub"].list_value().values().Get(0).string_value());
}
// Build authorized presenter (azp)
if (claims->find("azp") != claims->end()) {
payload->set_presenter(
(*claims)["azp"].list_value().values().Get(0).string_value());
}

return true;
}

bool AuthnUtils::ExtractOriginalPayload(const std::string& token,
std::string* original_payload) {
auto result = Wasm::Common::JsonParse(token);
if (!result.has_value()) {
return false;
}
auto json_obj = result.value();

if (!json_obj.contains(kExchangedTokenOriginalPayload)) {
return false;
}

auto original_payload_obj =
Wasm::Common::JsonGetField<Wasm::Common::JsonObject>(
json_obj, kExchangedTokenOriginalPayload);
if (original_payload_obj.detail() !=
Wasm::Common::JsonParserResultDetail::OK) {
return false;
}
*original_payload = original_payload_obj.value().dump();

return true;
}

} // namespace AuthN
} // namespace Extensions
41 changes: 41 additions & 0 deletions extensions/authn/authn_utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/* Copyright 2020 Istio Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once

#include "absl/strings/string_view.h"
#include "src/istio/authn/context.pb.h"

namespace Extensions {
namespace AuthN {

// AuthnUtils class provides utility functions used for authentication.
class AuthnUtils {
public:
// Parse JWT payload string (which typically is the output from jwt filter)
// and populate JwtPayload object. Return true if input string can be parsed
// successfully. Otherwise, return false.
static bool ProcessJwtPayload(const std::string& jwt_payload_str,
istio::authn::JwtPayload* payload);

// Parses the original_payload in an exchanged JWT.
// Returns true if original_payload can be
// parsed successfully. Otherwise, returns false.
static bool ExtractOriginalPayload(const std::string& token,
std::string* original_payload);
};

} // namespace AuthN
} // namespace Extensions
Loading