Skip to content
Draft
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
1 change: 1 addition & 0 deletions cilium/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ envoy_cc_library(
"@envoy//source/common/common:logger_lib",
"@envoy//source/common/network:address_lib",
"@envoy//source/common/router:config_utility_lib",
"@envoy_api//envoy/config/core/v3:pkg_cc_proto",
],
)

Expand Down
2 changes: 1 addition & 1 deletion cilium/api/bpf_metadata.proto
Original file line number Diff line number Diff line change
Expand Up @@ -85,5 +85,5 @@ message BpfMetadata {
google.protobuf.Duration cache_gc_interval = 15;

// Configuration for the source of NPDS updates. Currently this field is not supported.
envoy.config.core.v3.ApiConfigSource npds_config = 16;
envoy.config.core.v3.ConfigSource npds_config = 16;
}
47 changes: 33 additions & 14 deletions cilium/bpf_metadata.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include "envoy/api/io_error.h"
#include "envoy/common/exception.h"
#include "envoy/config/core/v3/config_source.pb.h"
#include "envoy/config/core/v3/socket_option.pb.h"
#include "envoy/network/address.h"
#include "envoy/network/filter.h"
Expand Down Expand Up @@ -178,21 +179,29 @@ SINGLETON_MANAGER_REGISTRATION(cilium_network_policy);

namespace {

std::shared_ptr<const Cilium::PolicyHostMap>
createHostMap(Server::Configuration::ListenerFactoryContext& context) {
absl::StatusOr<std::shared_ptr<const Cilium::PolicyHostMap>>
createHostMap(Server::Configuration::ListenerFactoryContext& context,
const absl::optional<envoy::config::core::v3::ConfigSource> npds_config) {
return context.serverFactoryContext().singletonManager().getTyped<const Cilium::PolicyHostMap>(
SINGLETON_MANAGER_REGISTERED_NAME(cilium_host_map), [&context] {
SINGLETON_MANAGER_REGISTERED_NAME(cilium_host_map), [&context, npds_config] {
auto map = std::make_shared<Cilium::PolicyHostMap>(context.serverFactoryContext());
map->startSubscription(context.serverFactoryContext());
absl::Status subscription_status = absl::OkStatus();
map->startSubscription(context.serverFactoryContext(), npds_config, subscription_status);
RETURN_IF_NOT_OK_REF(subscription_status);
return map;
});
}

std::shared_ptr<const Cilium::NetworkPolicyMap>
createPolicyMap(Server::Configuration::FactoryContext& context) {
absl::StatusOr<std::shared_ptr<const Cilium::NetworkPolicyMap>>
createPolicyMap(Server::Configuration::FactoryContext& context,
const absl::optional<envoy::config::core::v3::ConfigSource> npds_config) {
return context.serverFactoryContext().singletonManager().getTyped<const Cilium::NetworkPolicyMap>(
SINGLETON_MANAGER_REGISTERED_NAME(cilium_network_policy),
[&context] { return std::make_shared<Cilium::NetworkPolicyMap>(context, true); });
SINGLETON_MANAGER_REGISTERED_NAME(cilium_network_policy), [&context, npds_config] {
absl::Status creation_status = absl::OkStatus();
auto policy_map = std::make_shared<Cilium::NetworkPolicyMap>(context, npds_config, creation_status, true);
RETURN_IF_NOT_OK_REF(creation_status);
return policy_map;
});
}

} // namespace
Expand All @@ -214,9 +223,6 @@ Config::Config(const ::cilium::BpfMetadata& config,
ipcache_entry_ttl_(
PROTOBUF_GET_MS_OR_DEFAULT(config, cache_entry_ttl, DEFAULT_CACHE_ENTRY_TTL_MS)),
random_(context.serverFactoryContext().api().randomGenerator()) {
if (config.has_npds_config()) {
throw EnvoyException("cilium.bpf_metadata: npds_config is not yet supported");
}
if (is_l7lb_ && is_ingress_) {
throw EnvoyException("cilium.bpf_metadata: is_l7lb may not be set with is_ingress");
}
Expand All @@ -234,9 +240,16 @@ Config::Config(const ::cilium::BpfMetadata& config,
fmt::format("cilium.bpf_metadata: ipv6_source_address is not an IPv6 address: {}",
config.ipv6_source_address()));
}

const absl::optional<envoy::config::core::v3::ConfigSource> npds_config =
config.has_npds_config() ? absl::make_optional(config.npds_config()) : absl::nullopt;
if (config.use_nphds()) {
hosts_ = createHostMap(context);
hosts_or_error = createHostMap(context, npds_config);
if (!hosts_or_error.ok()) {
throw EnvoyException(fmt::format("cilium.bpf_metadata: Failed to create PolicyHostMap: {}",
hosts_or_error.status().message()));
} else {
hosts_ = hosts_or_error.value();
}
}

// Note: all instances use the bpf root of the first filter with non-empty
Expand Down Expand Up @@ -273,7 +286,13 @@ Config::Config(const ::cilium::BpfMetadata& config,
// instances!
// Only created if either ipcache_ or hosts_ map exists
if (ipcache_ || hosts_) {
npmap_ = createPolicyMap(context);
npmap_or_error = createPolicyMap(context, npds_config);
if (!npmap_or_error.ok()) {
throw EnvoyException(fmt::format("cilium.bpf_metadata: Failed to create PolicyMap: {}",
npmap_or_error.status().message()));
} else {
npmap_ = npmap_or_error.value();
}
}
}

Expand Down
8 changes: 4 additions & 4 deletions cilium/grpc_subscription.cc
Original file line number Diff line number Diff line change
Expand Up @@ -141,13 +141,13 @@ envoy::config::core::v3::ConfigSource getCiliumXDSAPIConfig() {
envoy::config::core::v3::ConfigSource cilium_xds_api_config = getCiliumXDSAPIConfig();

std::unique_ptr<Config::GrpcSubscriptionImpl>
subscribe(const std::string& type_url, const LocalInfo::LocalInfo& local_info,
Upstream::ClusterManager& cm, Event::Dispatcher& dispatcher,
Random::RandomGenerator& random, Stats::Scope& scope,
subscribe(const absl::string_view type_url,
const LocalInfo::LocalInfo& local_info, Upstream::ClusterManager& cm,
Event::Dispatcher& dispatcher, Random::RandomGenerator& random, Stats::Scope& scope,
Config::SubscriptionCallbacks& callbacks,
Config::OpaqueResourceDecoderSharedPtr resource_decoder,
std::chrono::milliseconds init_fetch_timeout) {
const envoy::config::core::v3::ApiConfigSource& api_config_source =
const envoy::config::core::v3::ApiConfigSource& api_config_source =
cilium_xds_api_config.api_config_source();
THROW_IF_NOT_OK(Config::Utility::checkApiConfigSourceSubscriptionBackingCluster(
cm.primaryClusters(), api_config_source));
Expand Down
8 changes: 5 additions & 3 deletions cilium/grpc_subscription.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
#include "source/extensions/config_subscription/grpc/grpc_mux_impl.h"
#include "source/extensions/config_subscription/grpc/grpc_subscription_impl.h"

#include "absl/types/optional.h"

namespace Envoy {
namespace Cilium {

Expand Down Expand Up @@ -47,9 +49,9 @@ class GrpcMuxImpl : public Config::GrpcMuxImpl {
};

std::unique_ptr<Config::GrpcSubscriptionImpl>
subscribe(const std::string& type_url, const LocalInfo::LocalInfo& local_info,
Upstream::ClusterManager& cm, Event::Dispatcher& dispatcher,
Random::RandomGenerator& random, Stats::Scope& scope,
subscribe(const absl::string_view type_url,
const LocalInfo::LocalInfo& local_info, Upstream::ClusterManager& cm,
Event::Dispatcher& dispatcher, Random::RandomGenerator& random, Stats::Scope& scope,
Config::SubscriptionCallbacks& callbacks,
Config::OpaqueResourceDecoderSharedPtr resource_decoder,
std::chrono::milliseconds init_fetch_timeout = std::chrono::milliseconds(0));
Expand Down
35 changes: 30 additions & 5 deletions cilium/host_map.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <vector>

#include "envoy/common/exception.h"
#include "envoy/config/core/v3/config_source.pb.h"
#include "envoy/config/subscription.h"
#include "envoy/event/dispatcher.h"
#include "envoy/server/factory_context.h"
Expand All @@ -24,12 +25,17 @@
#include "absl/numeric/int128.h"
#include "absl/status/status.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "cilium/api/nphds.pb.h"
#include "cilium/grpc_subscription.h"

namespace Envoy {
namespace Cilium {

namespace {

constexpr absl::string_view NetworkPolicyHostsTypeUrl = "type.googleapis.com/cilium.NetworkPolicyHosts";

template <typename T>
unsigned int checkPrefix(T addr, bool have_prefix, unsigned int plen, absl::string_view host) {
const unsigned int plen_max = sizeof(T) * 8;
Expand All @@ -46,6 +52,9 @@ unsigned int checkPrefix(T addr, bool have_prefix, unsigned int plen, absl::stri
return plen;
}

}// namespace


struct ThreadLocalHostMapInitializer : public PolicyHostMap::ThreadLocalHostMap {
protected:
friend class PolicyHostMap; // PolicyHostMap can insert();
Expand Down Expand Up @@ -170,11 +179,27 @@ PolicyHostMap::PolicyHostMap(Server::Configuration::CommonFactoryContext& contex
scope_ = context.serverScope().createScope(name_);
}

void PolicyHostMap::startSubscription(Server::Configuration::CommonFactoryContext& context) {
subscription_ = subscribe("type.googleapis.com/cilium.NetworkPolicyHosts", context.localInfo(),
context.clusterManager(), context.mainThreadDispatcher(),
context.api().randomGenerator(), *scope_, *this,
std::make_shared<Cilium::PolicyHostDecoder>());
void PolicyHostMap::startSubscription(
Server::Configuration::ServerFactoryContext& context,
const absl::optional<envoy::config::core::v3::ConfigSource> npds_config, absl::Status& subscription_status) {
if (npds_config.has_value()) {
if (!npds_config.value().has_api_config_source() || npds_config.value().config_source_specifier_case() !=
envoy::config::core::v3::ConfigSource::kAds) {
subscription_status = absl::InvalidArgumentError(
"cilium.bpf_metadata: npds_config must have api_config_source set (with type ads)");
return;
}
subscription_ = THROW_OR_RETURN_VALUE(
context.clusterManager().subscriptionFactory().subscriptionOverAdsGrpcMux(
context.xdsManager().adsMux(), npds_config.value(), NetworkPolicyHostsTypeUrl,
*scope_, *this, std::make_shared<Cilium::PolicyHostDecoder>(), {}), Config::SubscriptionPtr);
} else {
subscription_ = subscribe(NetworkPolicyHostsTypeUrl,
context.localInfo(), context.clusterManager(),
context.mainThreadDispatcher(), context.api().randomGenerator(),
*scope_, *this, std::make_shared<Cilium::PolicyHostDecoder>());
}

subscription_->start({});
}

Expand Down
6 changes: 5 additions & 1 deletion cilium/host_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <vector>

#include "envoy/common/exception.h"
#include "envoy/config/core/v3/config_source.pb.h"
#include "envoy/config/subscription.h"
#include "envoy/network/address.h"
#include "envoy/protobuf/message_validator.h"
Expand All @@ -33,6 +34,7 @@
#include "absl/container/flat_hash_map.h"
#include "absl/numeric/int128.h"
#include "absl/status/status.h"
#include "absl/types/optional.h"
#include "cilium/api/nphds.pb.h"
#include "cilium/api/nphds.pb.validate.h" // IWYU pragma: keep
#include "cilium/policy_id.h"
Expand Down Expand Up @@ -101,7 +103,9 @@ class PolicyHostMap : public Singleton::Instance,
ENVOY_LOG(debug, "Cilium PolicyHostMap({}): PolicyHostMap is deleted NOW!", name_);
}

void startSubscription(Server::Configuration::CommonFactoryContext& context);
void
startSubscription(Server::Configuration::ServerFactoryContext& context,
const absl::optional<envoy::config::core::v3::ConfigSource> npds_config, absl::Status& subscription_status);

// This is used for testing with a file-based subscription
void startSubscription(std::unique_ptr<Envoy::Config::Subscription>&& subscription) {
Expand Down
40 changes: 33 additions & 7 deletions cilium/network_policy.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "envoy/common/optref.h"
#include "envoy/config/core/v3/address.pb.h"
#include "envoy/config/core/v3/base.pb.h"
#include "envoy/config/core/v3/config_source.pb.h"
#include "envoy/config/subscription.h"
#include "envoy/http/header_map.h"
#include "envoy/init/manager.h"
Expand Down Expand Up @@ -59,6 +60,12 @@
#include "cilium/ipcache.h"
#include "cilium/secret_watcher.h"

namespace {

constexpr std::string NetworkPolicyTypeUrl = "type.googleapis.com/cilium.NetworkPolicy";

}//namespace

namespace fmt {

template <> struct formatter<Envoy::Cilium::RuleVerdict> {
Expand Down Expand Up @@ -1823,7 +1830,9 @@ class PolicyInstanceImpl : public PolicyInstance {

// Common base constructor
// This is used directly for testing with a file-based subscription
NetworkPolicyMap::NetworkPolicyMap(Server::Configuration::FactoryContext& context, bool subscribe)
NetworkPolicyMap::NetworkPolicyMap(
Server::Configuration::FactoryContext& context,
const absl::optional<envoy::config::core::v3::ConfigSource> npds_config, absl::Status& creation_status, bool subscribe)
: context_(context.serverFactoryContext()) {
impl_ = std::make_unique<NetworkPolicyMapImpl>(context);

Expand All @@ -1837,7 +1846,7 @@ NetworkPolicyMap::NetworkPolicyMap(Server::Configuration::FactoryContext& contex
}

if (subscribe) {
getImpl().startSubscription();
getImpl().startSubscription(npds_config, creation_status);
}
}

Expand Down Expand Up @@ -1891,11 +1900,28 @@ NetworkPolicyMapImpl::~NetworkPolicyMapImpl() {
delete load();
}

void NetworkPolicyMapImpl::startSubscription() {
subscription_ = subscribe("type.googleapis.com/cilium.NetworkPolicy", context_.localInfo(),
context_.clusterManager(), context_.mainThreadDispatcher(),
context_.api().randomGenerator(), *npds_stats_scope_, *this,
std::make_shared<NetworkPolicyDecoder>());
void NetworkPolicyMapImpl::startSubscription(
const absl::optional<envoy::config::core::v3::ConfigSource> npds_config,
absl::Status& subscription_status) {
if (npds_config.has_value()) {
if (!npds_config.value().has_api_config_source() || npds_config.value().config_source_specifier_case() !=
envoy::config::core::v3::ConfigSource::kAds) {
subscription_status = absl::InvalidArgumentError(
"cilium.bpf_metadata: npds_config must have api_config_source set (with type ads)");
return;
}
subscription_ = THROW_OR_RETURN_VALUE(
context_.clusterManager().subscriptionFactory().subscriptionOverAdsGrpcMux(
context_.xdsManager().adsMux(), npds_config.value(), NetworkPolicyTypeUrl,
*scope_, *this, std::make_shared<Cilium::PolicyHostDecoder>(), {}), Config::SubscriptionPtr);
} else {
subscription_ = subscribe(NetworkPolicyTypeUrl, npds_config,
context_.localInfo(), context_.clusterManager(),
context_.mainThreadDispatcher(), context_.api().randomGenerator(),
*npds_stats_scope_, *this, std::make_shared<NetworkPolicyDecoder>());
}

subscription_->start({});
}

void NetworkPolicyMapImpl::tlsWrapperMissingPolicyInc() const {
Expand Down
9 changes: 7 additions & 2 deletions cilium/network_policy.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "envoy/common/pure.h"
#include "envoy/common/regex.h"
#include "envoy/config/core/v3/base.pb.h"
#include "envoy/config/core/v3/config_source.pb.h"
#include "envoy/config/subscription.h"
#include "envoy/http/header_map.h"
#include "envoy/network/address.h"
Expand Down Expand Up @@ -43,6 +44,7 @@
#include "absl/status/status.h"
#include "absl/strings/ascii.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "cilium/accesslog.h"
#include "cilium/api/npds.pb.h"
#include "cilium/api/npds.pb.validate.h" // IWYU pragma: keep
Expand Down Expand Up @@ -235,7 +237,8 @@ class NetworkPolicyMapImpl : public Envoy::Config::SubscriptionCallbacks,
NetworkPolicyMapImpl(Server::Configuration::FactoryContext& context);
~NetworkPolicyMapImpl() override;

void startSubscription();
void
startSubscription(const absl::optional<envoy::config::core::v3::ConfigSource> npds_config, absl::Status& subscription_status);

// This is used for testing with a file-based subscription
void startSubscription(std::unique_ptr<Envoy::Config::Subscription>&& subscription) {
Expand Down Expand Up @@ -339,7 +342,9 @@ class AllowAllEgressPolicyInstanceImpl;

class NetworkPolicyMap : public Singleton::Instance, public Logger::Loggable<Logger::Id::config> {
public:
NetworkPolicyMap(Server::Configuration::FactoryContext& context, bool subscribe = false);
NetworkPolicyMap(Server::Configuration::FactoryContext& context,
const absl::optional<envoy::config::core::v3::ConfigSource> npds_config,
absl::Status& creation_status, bool subscribe = false);
~NetworkPolicyMap() override;

// This is used for testing with a file-based subscription
Expand Down
2 changes: 1 addition & 1 deletion tests/bpf_metadata.cc
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ createPolicyMap(const std::string& config,
policy_path, context.serverFactoryContext().api()));
Envoy::Config::SubscriptionStats stats =
Envoy::Config::Utility::generateStats(context.scope());
auto map = std::make_shared<Cilium::NetworkPolicyMap>(context);
auto map = std::make_shared<Cilium::NetworkPolicyMap>(context, absl::nullopt);
auto subscription = std::make_unique<Envoy::Config::FilesystemSubscriptionImpl>(
context.serverFactoryContext().mainThreadDispatcher(),
Envoy::Config::makePathConfigSource(policy_path), map->getImpl(),
Expand Down
9 changes: 6 additions & 3 deletions tests/metadata_config_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -224,12 +224,15 @@ class MetadataConfigTest : public testing::Test {
std::list<Init::TargetHandlePtr> target_handles_;
};

TEST_F(MetadataConfigTest, NpdsConfigNotSupported) {
TEST_F(MetadataConfigTest, NpdsConfigSupported) {
::cilium::BpfMetadata config{};
config.set_use_original_source_address(true);
config.set_is_l7lb(true);
config.set_ipv4_source_address("127.0.0.1");
config.set_ipv6_source_address("::1");
config.mutable_npds_config()->set_api_type(envoy::config::core::v3::ApiConfigSource::GRPC);

EXPECT_THROW_WITH_MESSAGE(initialize(config), EnvoyException,
"cilium.bpf_metadata: npds_config is not yet supported");
EXPECT_NO_THROW(initialize(config));
}

TEST_F(MetadataConfigTest, EmptyConfig) {
Expand Down
Loading