Skip to content

Commit

Permalink
auth: AttributeContext utilities
Browse files Browse the repository at this point in the history
Signed-off-by: Chris Roche <croche@lyft.com>
  • Loading branch information
Chris Roche committed May 9, 2018
1 parent 5180b24 commit a34fde7
Show file tree
Hide file tree
Showing 7 changed files with 162 additions and 123 deletions.
22 changes: 22 additions & 0 deletions source/extensions/filters/common/auth/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
licenses(["notice"]) # Apache 2

load(
"//bazel:envoy_build_system.bzl",
"envoy_cc_library",
"envoy_package",
)

envoy_package()

envoy_cc_library(
name = "attribute_context_lib",
hdrs = ["attribute_context.h"],
srcs = ["attribute_context.cc"],
deps = [
"//include/envoy/http:filter_interface",
"//include/envoy/http:header_map_interface",
"//source/common/http:utility_lib",
"//source/common/network:utility_lib",
"@envoy_api//envoy/service/auth/v2alpha:attribute_context_cc",
],
)
91 changes: 91 additions & 0 deletions source/extensions/filters/common/auth/attribute_context.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#include "extensions/filters/common/auth/attribute_context.h"

#include "common/http/utility.h"
#include "common/network/utility.h"

namespace Envoy {
namespace Extensions {
namespace Filters {
namespace Common {
namespace Auth {

void AttributeContextUtils::setSourcePeer(envoy::service::auth::v2alpha::AttributeContext& context,
const Network::Connection& connection,
const std::string& service) {
setPeer(*context.mutable_source(), connection, service, false);
}

void AttributeContextUtils::setDestinationPeer(
envoy::service::auth::v2alpha::AttributeContext& context,
const Network::Connection& connection) {
setPeer(*context.mutable_destination(), connection, "", true);
}

void AttributeContextUtils::setPeer(envoy::service::auth::v2alpha::AttributeContext_Peer& peer,
const Network::Connection& connection,
const std::string& service, const bool local) {

auto addr = local ? connection.localAddress() : connection.remoteAddress();
Envoy::Network::Utility::addressToProtobufAddress(*addr, *peer.mutable_address());

if (!service.empty()) {
peer.set_service(service);
}

auto ssl = const_cast<Ssl::Connection*>(connection.ssl());
if (ssl) {
std::string principal = local ? ssl->uriSanLocalCertificate() : ssl->uriSanPeerCertificate();
if (principal.empty()) {
principal = local ? ssl->subjectLocalCertificate() : ssl->subjectPeerCertificate();
}
peer.set_principal(principal);
}
}

void AttributeContextUtils::setHttpRequest(
envoy::service::auth::v2alpha::AttributeContext& context,
const Envoy::Http::StreamDecoderFilterCallbacks* callbacks,
const Envoy::Http::HeaderMap& headers) {

auto req = context.mutable_request()->mutable_http();
auto sdfc = const_cast<Envoy::Http::StreamDecoderFilterCallbacks*>(callbacks);

auto start = ProtobufUtil::TimeUtil::MicrosecondsToTimestamp(
sdfc->requestInfo().startTime().time_since_epoch().count());
context.mutable_request()->mutable_time()->MergeFrom(start);

auto proto = sdfc->requestInfo().protocol();
if (proto) {
req->set_protocol(Envoy::Http::Utility::getProtocolString(proto.value()));
}

req->set_id(std::to_string(sdfc->streamId()));
req->set_size(sdfc->requestInfo().bytesReceived());

req->set_method(getHeaderStr(headers.Method()));
req->set_path(getHeaderStr(headers.Path()));
req->set_host(getHeaderStr(headers.Host()));
req->set_scheme(getHeaderStr(headers.Scheme()));
// TODO(rodaine): add query & fragment fields

auto mutable_headers = req->mutable_headers();
headers.iterate(
[](const Envoy::Http::HeaderEntry& e, void* ctx) {
auto mutable_headers = static_cast<
Envoy::Protobuf::Map<Envoy::ProtobufTypes::String, Envoy::ProtobufTypes::String>*>(ctx);
(*mutable_headers)[std::string(e.key().getStringView())] =
std::string(e.value().getStringView());
return Envoy::Http::HeaderMap::Iterate::Continue;
},
mutable_headers);
}

std::string AttributeContextUtils::getHeaderStr(const Envoy::Http::HeaderEntry* entry) {
return entry ? std::string(entry->value().getStringView()) : "";
}

} // namespace Auth
} // namespace Common
} // namespace Filters
} // namespace Extensions
} // namespace Envoy
38 changes: 38 additions & 0 deletions source/extensions/filters/common/auth/attribute_context.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#pragma once

#include <string>

#include "envoy/http/filter.h"
#include "envoy/http/header_map.h"
#include "envoy/network/connection.h"
#include "envoy/service/auth/v2alpha/attribute_context.pb.h"

namespace Envoy {
namespace Extensions {
namespace Filters {
namespace Common {
namespace Auth {

class AttributeContextUtils {
public:
static void setSourcePeer(envoy::service::auth::v2alpha::AttributeContext& context,
const Network::Connection& connection, const std::string& service);
static void setDestinationPeer(envoy::service::auth::v2alpha::AttributeContext& context,
const Network::Connection& connection);
static void setHttpRequest(envoy::service::auth::v2alpha::AttributeContext& context,
const Envoy::Http::StreamDecoderFilterCallbacks* callbacks,
const Envoy::Http::HeaderMap& headers);

private:
static void setPeer(envoy::service::auth::v2alpha::AttributeContext_Peer& peer,
const Network::Connection& connection, const std::string& service,
const bool local);

static std::string getHeaderStr(const Envoy::Http::HeaderEntry* entry);
};

} // namespace Auth
} // namespace Common
} // namespace Filters
} // namespace Extensions
} // namespace Envoy
3 changes: 1 addition & 2 deletions source/extensions/filters/common/ext_authz/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,8 @@ envoy_cc_library(
"//source/common/common:assert_lib",
"//source/common/grpc:async_client_lib",
"//source/common/http:headers_lib",
"//source/common/http:utility_lib",
"//source/common/network:utility_lib",
"//source/common/protobuf",
"//source/common/tracing:http_tracer_lib",
"//source/extensions/filters/common/auth:attribute_context_lib",
],
)
114 changes: 8 additions & 106 deletions source/extensions/filters/common/ext_authz/ext_authz_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@
#include "common/common/assert.h"
#include "common/grpc/async_client_impl.h"
#include "common/http/headers.h"
#include "common/http/utility.h"
#include "common/network/utility.h"
#include "common/protobuf/protobuf.h"
#include "extensions/filters/common/auth/attribute_context.h"

namespace Envoy {
namespace Extensions {
Expand Down Expand Up @@ -67,104 +66,6 @@ void GrpcClientImpl::onFailure(Grpc::Status::GrpcStatus status, const std::strin
callbacks_ = nullptr;
}

void CheckRequestUtils::setAttrContextPeer(
envoy::service::auth::v2alpha::AttributeContext_Peer& peer,
const Network::Connection& connection, const std::string& service, const bool local) {

// Set the address
auto addr = peer.mutable_address();
if (local) {
Envoy::Network::Utility::addressToProtobufAddress(*connection.localAddress(), *addr);
} else {
Envoy::Network::Utility::addressToProtobufAddress(*connection.remoteAddress(), *addr);
}

// Set the principal
// Preferably the SAN from the peer's cert or
// Subject from the peer's cert.
Ssl::Connection* ssl = const_cast<Ssl::Connection*>(connection.ssl());
if (ssl != nullptr) {
if (local) {
peer.set_principal(ssl->uriSanLocalCertificate());

if (peer.principal().empty()) {
peer.set_principal(ssl->subjectLocalCertificate());
}
} else {
peer.set_principal(ssl->uriSanPeerCertificate());

if (peer.principal().empty()) {
peer.set_principal(ssl->subjectPeerCertificate());
}
}
}

if (!service.empty()) {
peer.set_service(service);
}
}

std::string CheckRequestUtils::getHeaderStr(const Envoy::Http::HeaderEntry* entry) {
if (entry) {
// TODO(jmarantz): plumb absl::string_view further here; there's no need
// to allocate a temp string in the local uses.
return std::string(entry->value().getStringView());
}
return "";
}

void CheckRequestUtils::setHttpRequest(
::envoy::service::auth::v2alpha::AttributeContext_HttpRequest& httpreq,
const Envoy::Http::StreamDecoderFilterCallbacks* callbacks,
const Envoy::Http::HeaderMap& headers) {

// Set id
// The streamId is not qualified as a const. Although it is as it does not modify the object.
Envoy::Http::StreamDecoderFilterCallbacks* sdfc =
const_cast<Envoy::Http::StreamDecoderFilterCallbacks*>(callbacks);
httpreq.set_id(std::to_string(sdfc->streamId()));

// Set method
httpreq.set_method(getHeaderStr(headers.Method()));
// Set path
httpreq.set_path(getHeaderStr(headers.Path()));
// Set host
httpreq.set_host(getHeaderStr(headers.Host()));
// Set scheme
httpreq.set_scheme(getHeaderStr(headers.Scheme()));

// Set size
// need to convert to google buffer 64t;
httpreq.set_size(sdfc->requestInfo().bytesReceived());

// Set protocol
if (sdfc->requestInfo().protocol()) {
httpreq.set_protocol(
Envoy::Http::Utility::getProtocolString(sdfc->requestInfo().protocol().value()));
}

// Fill in the headers
auto mutable_headers = httpreq.mutable_headers();
headers.iterate(
[](const Envoy::Http::HeaderEntry& e, void* ctx) {
Envoy::Protobuf::Map<Envoy::ProtobufTypes::String, Envoy::ProtobufTypes::String>*
mutable_headers = static_cast<
Envoy::Protobuf::Map<Envoy::ProtobufTypes::String, Envoy::ProtobufTypes::String>*>(
ctx);
(*mutable_headers)[std::string(e.key().getStringView())] =
std::string(e.value().getStringView());
return Envoy::Http::HeaderMap::Iterate::Continue;
},
mutable_headers);
}

void CheckRequestUtils::setAttrContextRequest(
::envoy::service::auth::v2alpha::AttributeContext_Request& req,
const Envoy::Http::StreamDecoderFilterCallbacks* callbacks,
const Envoy::Http::HeaderMap& headers) {
setHttpRequest(*req.mutable_http(), callbacks, headers);
}

void CheckRequestUtils::createHttpCheck(const Envoy::Http::StreamDecoderFilterCallbacks* callbacks,
const Envoy::Http::HeaderMap& headers,
envoy::service::auth::v2alpha::CheckRequest& request) {
Expand All @@ -174,11 +75,12 @@ void CheckRequestUtils::createHttpCheck(const Envoy::Http::StreamDecoderFilterCa
Envoy::Http::StreamDecoderFilterCallbacks* cb =
const_cast<Envoy::Http::StreamDecoderFilterCallbacks*>(callbacks);

const std::string service = getHeaderStr(headers.EnvoyDownstreamServiceCluster());
auto hdr = headers.EnvoyDownstreamServiceCluster();
std::string service = hdr ? std::string(hdr->value().getStringView()) : "";

setAttrContextPeer(*attrs->mutable_source(), *cb->connection(), service, false);
setAttrContextPeer(*attrs->mutable_destination(), *cb->connection(), "", true);
setAttrContextRequest(*attrs->mutable_request(), callbacks, headers);
Auth::AttributeContextUtils::setSourcePeer(*attrs, *cb->connection(), service);
Auth::AttributeContextUtils::setDestinationPeer(*attrs, *cb->connection());
Auth::AttributeContextUtils::setHttpRequest(*attrs, callbacks, headers);
}

void CheckRequestUtils::createTcpCheck(const Network::ReadFilterCallbacks* callbacks,
Expand All @@ -187,8 +89,8 @@ void CheckRequestUtils::createTcpCheck(const Network::ReadFilterCallbacks* callb
auto attrs = request.mutable_attributes();

Network::ReadFilterCallbacks* cb = const_cast<Network::ReadFilterCallbacks*>(callbacks);
setAttrContextPeer(*attrs->mutable_source(), cb->connection(), "", false);
setAttrContextPeer(*attrs->mutable_destination(), cb->connection(), "", true);
Auth::AttributeContextUtils::setSourcePeer(*attrs, cb->connection(), "");
Auth::AttributeContextUtils::setDestinationPeer(*attrs, cb->connection());
}

} // namespace ExtAuthz
Expand Down
13 changes: 0 additions & 13 deletions source/extensions/filters/common/ext_authz/ext_authz_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,19 +98,6 @@ class CheckRequestUtils {
*/
static void createTcpCheck(const Network::ReadFilterCallbacks* callbacks,
envoy::service::auth::v2alpha::CheckRequest& request);

private:
static void setAttrContextPeer(envoy::service::auth::v2alpha::AttributeContext_Peer& peer,
const Network::Connection& connection, const std::string& service,
const bool local);
static void setHttpRequest(::envoy::service::auth::v2alpha::AttributeContext_HttpRequest& httpreq,
const Envoy::Http::StreamDecoderFilterCallbacks* callbacks,
const Envoy::Http::HeaderMap& headers);
static void setAttrContextRequest(::envoy::service::auth::v2alpha::AttributeContext_Request& req,
const Envoy::Http::StreamDecoderFilterCallbacks* callbacks,
const Envoy::Http::HeaderMap& headers);
static std::string getHeaderStr(const Envoy::Http::HeaderEntry* entry);
static Envoy::Http::HeaderMap::Iterate fillHttpHeaders(const Envoy::Http::HeaderEntry&, void*);
};

} // namespace ExtAuthz
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"

using testing::_;
using testing::AtLeast;
using testing::Invoke;
using testing::Ref;
using testing::Return;
using testing::ReturnPointee;
using testing::ReturnRef;
using testing::WithArg;
using testing::_;

namespace Envoy {
namespace Extensions {
Expand Down Expand Up @@ -163,7 +163,7 @@ TEST_F(CheckRequestUtilsTest, BasicHttp) {
EXPECT_CALL(Const(connection_), ssl()).Times(2).WillRepeatedly(Return(&ssl_));
EXPECT_CALL(callbacks_, streamId()).WillOnce(Return(0));
EXPECT_CALL(callbacks_, requestInfo()).Times(3).WillRepeatedly(ReturnRef(req_info_));
EXPECT_CALL(req_info_, protocol()).Times(2).WillRepeatedly(ReturnPointee(&protocol_));
EXPECT_CALL(req_info_, protocol()).WillOnce(ReturnPointee(&protocol_));
CheckRequestUtils::createHttpCheck(&callbacks_, headers, request);
}

Expand Down

0 comments on commit a34fde7

Please sign in to comment.