Skip to content

Commit

Permalink
tls_wrapper: Use raw socket with non-TLS policy
Browse files Browse the repository at this point in the history
Cilium tls_wrapper should allow raw socket to be used if policy allows
without TLS context.

Also check for SNI when getting TLS context so that the one matching the
SNI is used if multiple are available.

Add policy tests validating the policy functionality.

Signed-off-by: Jarno Rajahalme <jarno@isovalent.com>
  • Loading branch information
jrajahalme committed Nov 9, 2024
1 parent cd22d9f commit 2190d8b
Show file tree
Hide file tree
Showing 5 changed files with 436 additions and 51 deletions.
15 changes: 10 additions & 5 deletions cilium/network_filter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,10 @@ Network::FilterStatus Instance::onNewConnection() {
if (option->ingress_source_identity_ != 0) {
auto ingress_port_policy = option->initial_policy_->findPortPolicy(true, destination_port_);
if (!ingress_port_policy.allowed(option->ingress_source_identity_, sni)) {
ENVOY_CONN_LOG(debug,
"cilium.network: ingress policy drop for source identity: {} port: {}",
conn, option->ingress_source_identity_, destination_port_);
ENVOY_CONN_LOG(
debug,
"cilium.network: ingress policy DROP for source identity: {} port: {} sni: \"{}\"",
conn, option->ingress_source_identity_, destination_port_, sni);
return false;
}
}
Expand All @@ -161,9 +162,13 @@ Network::FilterStatus Instance::onNewConnection() {
remote_id_ = option->ingress_ ? option->identity_ : destination_identity;
if (!port_policy.allowed(remote_id_, sni)) {
// Connection not allowed by policy
ENVOY_CONN_LOG(warn, "cilium.network: Policy DENY on id: {} port: {}", conn, remote_id_,
destination_port_);
ENVOY_CONN_LOG(debug, "cilium.network: Policy DENY on id: {} port: {} sni: \"{}\"", conn,
remote_id_, destination_port_, sni);
return false;
} else {
// Connection allowed by policy
ENVOY_CONN_LOG(debug, "cilium.network: Policy ALLOW on id: {} port: {} sni: \"{}\"", conn,
remote_id_, destination_port_, sni);
}

const std::string& policy_name = option->pod_ip_;
Expand Down
58 changes: 36 additions & 22 deletions cilium/network_policy.cc
Original file line number Diff line number Diff line change
Expand Up @@ -489,22 +489,30 @@ class PortNetworkPolicyRule : public Logger::Loggable<Logger::Id::config> {
return true; // allowed by default
}

Ssl::ContextSharedPtr getServerTlsContext(uint32_t remote_id,
const Ssl::ContextConfig** config) const {
Ssl::ContextSharedPtr getServerTlsContext(uint32_t remote_id, absl::string_view sni,
const Ssl::ContextConfig** config,
bool& raw_socket_allowed) const {
bool denied = false;
if (server_context_ && allowed(remote_id, denied)) {
*config = &server_context_->getTlsContextConfig();
return server_context_->getTlsContext();
if (allowed(remote_id, sni, denied)) {
if (server_context_) {
*config = &server_context_->getTlsContextConfig();
return server_context_->getTlsContext();
}
raw_socket_allowed = true;
}
return nullptr;
}

Ssl::ContextSharedPtr getClientTlsContext(uint32_t remote_id,
const Ssl::ContextConfig** config) const {
Ssl::ContextSharedPtr getClientTlsContext(uint32_t remote_id, absl::string_view sni,
const Ssl::ContextConfig** config,
bool& raw_socket_allowed) const {
bool denied = false;
if (client_context_ && allowed(remote_id, denied)) {
*config = &client_context_->getTlsContextConfig();
return client_context_->getTlsContext();
if (allowed(remote_id, sni, denied)) {
if (client_context_) {
*config = &client_context_->getTlsContextConfig();
return client_context_->getTlsContext();
}
raw_socket_allowed = true;
}
return nullptr;
}
Expand Down Expand Up @@ -671,20 +679,24 @@ class PortNetworkPolicyRules : public Logger::Loggable<Logger::Id::config> {
return allowed && !denied;
}

Ssl::ContextSharedPtr getServerTlsContext(uint32_t remote_id,
const Ssl::ContextConfig** config) const {
Ssl::ContextSharedPtr getServerTlsContext(uint32_t remote_id, absl::string_view sni,
const Ssl::ContextConfig** config,
bool& raw_socket_allowed) const {
for (const auto& rule : rules_) {
Ssl::ContextSharedPtr server_context = rule->getServerTlsContext(remote_id, config);
Ssl::ContextSharedPtr server_context =
rule->getServerTlsContext(remote_id, sni, config, raw_socket_allowed);
if (server_context)
return server_context;
}
return nullptr;
}

Ssl::ContextSharedPtr getClientTlsContext(uint32_t remote_id,
const Ssl::ContextConfig** config) const {
Ssl::ContextSharedPtr getClientTlsContext(uint32_t remote_id, absl::string_view sni,
const Ssl::ContextConfig** config,
bool& raw_socket_allowed) const {
for (const auto& rule : rules_) {
Ssl::ContextSharedPtr client_context = rule->getClientTlsContext(remote_id, config);
Ssl::ContextSharedPtr client_context =
rule->getClientTlsContext(remote_id, sni, config, raw_socket_allowed);
if (client_context)
return client_context;
}
Expand Down Expand Up @@ -787,21 +799,23 @@ bool PortPolicy::allowed(uint32_t remote_id,
});
}

Ssl::ContextSharedPtr PortPolicy::getServerTlsContext(uint32_t remote_id,
const Ssl::ContextConfig** config) const {
Ssl::ContextSharedPtr PortPolicy::getServerTlsContext(uint32_t remote_id, absl::string_view sni,
const Ssl::ContextConfig** config,
bool& raw_socket_allowed) const {
Ssl::ContextSharedPtr ret;
for_first_range([&](const PortNetworkPolicyRules& rules) -> bool {
ret = rules.getServerTlsContext(remote_id, config);
ret = rules.getServerTlsContext(remote_id, sni, config, raw_socket_allowed);
return ret != nullptr;
});
return ret;
}

Ssl::ContextSharedPtr PortPolicy::getClientTlsContext(uint32_t remote_id,
const Ssl::ContextConfig** config) const {
Ssl::ContextSharedPtr PortPolicy::getClientTlsContext(uint32_t remote_id, absl::string_view sni,
const Ssl::ContextConfig** config,
bool& raw_socket_allowed) const {
Ssl::ContextSharedPtr ret;
for_first_range([&](const PortNetworkPolicyRules& rules) -> bool {
ret = rules.getClientTlsContext(remote_id, config);
ret = rules.getClientTlsContext(remote_id, sni, config, raw_socket_allowed);
return ret != nullptr;
});
return ret;
Expand Down
14 changes: 10 additions & 4 deletions cilium/network_policy.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,18 @@ class PortPolicy : public Logger::Loggable<Logger::Id::config> {
bool allowed(uint32_t remote_id, const envoy::config::core::v3::Metadata& metadata) const;
// getServerTlsContext returns the server TLS context, if any. If a non-null pointer is returned,
// then also the config pointer '*config' is set.
Ssl::ContextSharedPtr getServerTlsContext(uint32_t remote_id,
const Ssl::ContextConfig** config) const;
// If '*config' is nullptr and 'raw_socket_allowed' is 'true' on return then the policy
// allows the connection without TLS and a raw socket should be used.
Ssl::ContextSharedPtr getServerTlsContext(uint32_t remote_id, absl::string_view sni,
const Ssl::ContextConfig** config,
bool& raw_socket_allowed) const;
// getClientTlsContext returns the client TLS context, if any. If a non-null pointer is returned,
// then also the config pointer '*config' is set.
Ssl::ContextSharedPtr getClientTlsContext(uint32_t remote_id,
const Ssl::ContextConfig** config) const;
// If '*config' is nullptr and 'raw_socket_allowed' is 'true' on return then the policy
// allows the connection without TLS and a raw socket should be used.
Ssl::ContextSharedPtr getClientTlsContext(uint32_t remote_id, absl::string_view sni,
const Ssl::ContextConfig** config,
bool& raw_socket_allowed) const;

private:
bool for_range(std::function<bool(const PortNetworkPolicyRules&, bool& denied)> allowed) const;
Expand Down
33 changes: 24 additions & 9 deletions cilium/tls_wrapper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ class SslSocketWrapper : public Network::TransportSocket {
void setTransportSocketCallbacks(Network::TransportSocketCallbacks& callbacks) override {
// Get the Cilium socket option from the callbacks in order to get the TLS
// configuration
const auto option = Cilium::GetSocketOption(callbacks.connection().socketOptions());
// Cilium socket option is only created if the (intial) policy for the local pod exists.
// If the policy requires TLS then a TLS socket is used, but if the policy does not require
// TLS a raw socket is used instead,
const auto& conn = callbacks.connection();
const auto option = Cilium::GetSocketOption(conn.socketOptions());
if (option) {
// Resolve the destination security ID and port
uint32_t destination_identity = 0;
Expand All @@ -58,13 +62,17 @@ class SslSocketWrapper : public Network::TransportSocket {
}
}

// get the requested server name from the connection, if any
const auto sni = conn.requestedServerName();

auto remote_id = option->ingress_ ? option->identity_ : destination_identity;
auto port_policy =
option->initial_policy_->findPortPolicy(option->ingress_, destination_port);
const Envoy::Ssl::ContextConfig* config;
Envoy::Ssl::ContextSharedPtr ctx = is_client
? port_policy.getClientTlsContext(remote_id, &config)
: port_policy.getServerTlsContext(remote_id, &config);
const Envoy::Ssl::ContextConfig* config = nullptr;
bool raw_socket_allowed = false;
Envoy::Ssl::ContextSharedPtr ctx =
is_client ? port_policy.getClientTlsContext(remote_id, sni, &config, raw_socket_allowed)
: port_policy.getServerTlsContext(remote_id, sni, &config, raw_socket_allowed);
if (ctx) {
// create the underlying SslSocket
auto status_or_socket = Extensions::TransportSockets::Tls::SslSocket::create(
Expand All @@ -77,6 +85,12 @@ class SslSocketWrapper : public Network::TransportSocket {
ENVOY_LOG_MISC(error, "Unable to create ssl socket {}",
status_or_socket.status().message());
}
} else if (config == nullptr && raw_socket_allowed) {
// Use RawBufferSocket when policy allows without TLS.
// If policy has TLS context config then a raw socket must NOT be used.
socket_ = std::make_unique<Network::RawBufferSocket>();
// Set the callbacks
socket_->setTransportSocketCallbacks(callbacks);
} else {
std::string ipStr("<none>");
if (option->ingress_) {
Expand All @@ -94,10 +108,11 @@ class SslSocketWrapper : public Network::TransportSocket {
ipStr = dip->addressAsString();
}
}
ENVOY_LOG_MISC(
warn, "cilium.tls_wrapper: Could not get {} TLS context for {} IP {} (id {}) port {}",
is_client ? "client" : "server", option->ingress_ ? "source" : "destination", ipStr,
remote_id, destination_port);
ENVOY_LOG_MISC(warn,
"cilium.tls_wrapper: Could not get {} TLS context for {} IP {} (id {}) port "
"{} sni \"{}\" and raw socket is not allowed",
is_client ? "client" : "server", option->ingress_ ? "source" : "destination",
ipStr, remote_id, destination_port, sni);
}
} else {
ENVOY_LOG_MISC(warn, "cilium.tls_wrapper: Can not correlate connection with Cilium Network "
Expand Down
Loading

0 comments on commit 2190d8b

Please sign in to comment.