blob: 80b713c03ddd0eca02144a6f891c4bff52229663 [file] [log] [blame]
// Copyright 2021 gRPC authors.
//
// 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 <grpc/support/port_platform.h>
#include "src/core/lib/security/authorization/evaluate_args.h"
#include "absl/strings/numbers.h"
#include "src/core/lib/address_utils/parse_address.h"
#include "src/core/lib/address_utils/sockaddr_utils.h"
#include "src/core/lib/gprpp/host_port.h"
#include "src/core/lib/security/credentials/tls/tls_utils.h"
#include "src/core/lib/slice/slice_utils.h"
namespace grpc_core {
namespace {
EvaluateArgs::PerChannelArgs::Address ParseEndpointUri(
absl::string_view uri_text) {
EvaluateArgs::PerChannelArgs::Address address;
absl::StatusOr<URI> uri = URI::Parse(uri_text);
if (!uri.ok()) {
gpr_log(GPR_DEBUG, "Failed to parse uri.");
return address;
}
absl::string_view host_view;
absl::string_view port_view;
if (!SplitHostPort(uri->path(), &host_view, &port_view)) {
gpr_log(GPR_DEBUG, "Failed to split %s into host and port.",
uri->path().c_str());
return address;
}
if (!absl::SimpleAtoi(port_view, &address.port)) {
gpr_log(GPR_DEBUG, "Port %s is out of range or null.",
std::string(port_view).c_str());
}
address.address_str = std::string(host_view);
grpc_error_handle error = grpc_string_to_sockaddr(
&address.address, address.address_str.c_str(), address.port);
if (error != GRPC_ERROR_NONE) {
gpr_log(GPR_DEBUG, "Address %s is not IPv4/IPv6. Error: %s",
address.address_str.c_str(), grpc_error_std_string(error).c_str());
}
GRPC_ERROR_UNREF(error);
return address;
}
} // namespace
EvaluateArgs::PerChannelArgs::PerChannelArgs(grpc_auth_context* auth_context,
grpc_endpoint* endpoint) {
if (auth_context != nullptr) {
transport_security_type = GetAuthPropertyValue(
auth_context, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME);
spiffe_id =
GetAuthPropertyValue(auth_context, GRPC_PEER_SPIFFE_ID_PROPERTY_NAME);
uri_sans = GetAuthPropertyArray(auth_context, GRPC_PEER_URI_PROPERTY_NAME);
dns_sans = GetAuthPropertyArray(auth_context, GRPC_PEER_DNS_PROPERTY_NAME);
common_name =
GetAuthPropertyValue(auth_context, GRPC_X509_CN_PROPERTY_NAME);
}
if (endpoint != nullptr) {
local_address = ParseEndpointUri(grpc_endpoint_get_local_address(endpoint));
peer_address = ParseEndpointUri(grpc_endpoint_get_peer(endpoint));
}
}
absl::string_view EvaluateArgs::GetPath() const {
absl::string_view path;
if (metadata_ != nullptr &&
metadata_->legacy_index()->named.path != nullptr) {
grpc_linked_mdelem* elem = metadata_->legacy_index()->named.path;
const grpc_slice& val = GRPC_MDVALUE(elem->md);
path = StringViewFromSlice(val);
}
return path;
}
absl::string_view EvaluateArgs::GetHost() const {
absl::string_view host;
if (metadata_ != nullptr &&
metadata_->legacy_index()->named.host != nullptr) {
grpc_linked_mdelem* elem = metadata_->legacy_index()->named.host;
const grpc_slice& val = GRPC_MDVALUE(elem->md);
host = StringViewFromSlice(val);
}
return host;
}
absl::string_view EvaluateArgs::GetMethod() const {
absl::string_view method;
if (metadata_ != nullptr &&
metadata_->legacy_index()->named.method != nullptr) {
grpc_linked_mdelem* elem = metadata_->legacy_index()->named.method;
const grpc_slice& val = GRPC_MDVALUE(elem->md);
method = StringViewFromSlice(val);
}
return method;
}
std::multimap<absl::string_view, absl::string_view> EvaluateArgs::GetHeaders()
const {
std::multimap<absl::string_view, absl::string_view> headers;
if (metadata_ == nullptr) {
return headers;
}
metadata_->ForEach([&](grpc_mdelem md) {
const grpc_slice& key = GRPC_MDKEY(md);
const grpc_slice& val = GRPC_MDVALUE(md);
headers.emplace(StringViewFromSlice(key), StringViewFromSlice(val));
});
return headers;
}
absl::optional<absl::string_view> EvaluateArgs::GetHeaderValue(
absl::string_view key, std::string* concatenated_value) const {
if (metadata_ == nullptr) {
return absl::nullopt;
}
return metadata_->GetValue(key, concatenated_value);
}
grpc_resolved_address EvaluateArgs::GetLocalAddress() const {
if (channel_args_ == nullptr) {
return {};
}
return channel_args_->local_address.address;
}
absl::string_view EvaluateArgs::GetLocalAddressString() const {
if (channel_args_ == nullptr) {
return "";
}
return channel_args_->local_address.address_str;
}
int EvaluateArgs::GetLocalPort() const {
if (channel_args_ == nullptr) {
return 0;
}
return channel_args_->local_address.port;
}
grpc_resolved_address EvaluateArgs::GetPeerAddress() const {
if (channel_args_ == nullptr) {
return {};
}
return channel_args_->peer_address.address;
}
absl::string_view EvaluateArgs::GetPeerAddressString() const {
if (channel_args_ == nullptr) {
return "";
}
return channel_args_->peer_address.address_str;
}
int EvaluateArgs::GetPeerPort() const {
if (channel_args_ == nullptr) {
return 0;
}
return channel_args_->peer_address.port;
}
absl::string_view EvaluateArgs::GetTransportSecurityType() const {
if (channel_args_ == nullptr) {
return "";
}
return channel_args_->transport_security_type;
}
absl::string_view EvaluateArgs::GetSpiffeId() const {
if (channel_args_ == nullptr) {
return "";
}
return channel_args_->spiffe_id;
}
std::vector<absl::string_view> EvaluateArgs::GetUriSans() const {
if (channel_args_ == nullptr) {
return {};
}
return channel_args_->uri_sans;
}
std::vector<absl::string_view> EvaluateArgs::GetDnsSans() const {
if (channel_args_ == nullptr) {
return {};
}
return channel_args_->dns_sans;
}
absl::string_view EvaluateArgs::GetCommonName() const {
if (channel_args_ == nullptr) {
return "";
}
return channel_args_->common_name;
}
} // namespace grpc_core