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 CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ extensions/upstreams/tcp @ggreenway @mattklein123
/*/extensions/filters/common/ext_authz @esmet @tyxia @ggreenway @antoniovleonti
/*/extensions/filters/http/ext_authz @esmet @tyxia @ggreenway @antoniovleonti
/*/extensions/filters/network/ext_authz @esmet @tyxia @ggreenway @antoniovleonti
/*/extensions/filters/udp/udp_proxy/session_filters/ext_authz @antonkanug @UNOWNED
# original dst
/*/extensions/filters/listener/original_dst @kyessenov @cpakulski @lambdai @nezdolik
# mongo proxy
Expand Down
1 change: 1 addition & 0 deletions api/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ proto_library(
"//envoy/extensions/filters/udp/dns_filter/v3:pkg",
"//envoy/extensions/filters/udp/dynamic_modules/v3:pkg",
"//envoy/extensions/filters/udp/udp_proxy/session/dynamic_forward_proxy/v3:pkg",
"//envoy/extensions/filters/udp/udp_proxy/session/ext_authz/v3:pkg",
"//envoy/extensions/filters/udp/udp_proxy/session/http_capsule/v3:pkg",
"//envoy/extensions/filters/udp/udp_proxy/v3:pkg",
"//envoy/extensions/formatter/cel/v3:pkg",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# DO NOT EDIT. This file is generated by tools/proto_format/proto_sync.py.

load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package")

licenses(["notice"]) # Apache 2

api_proto_package(
deps = [
"//envoy/config/core/v3:pkg",
"@xds//udpa/annotations:pkg",
],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
syntax = "proto3";

package envoy.extensions.filters.udp.udp_proxy.session.ext_authz.v3;

import "envoy/config/core/v3/grpc_service.proto";

import "google/protobuf/wrappers.proto";

import "udpa/annotations/status.proto";
import "validate/validate.proto";

option java_package = "io.envoyproxy.envoy.extensions.filters.udp.udp_proxy.session.ext_authz.v3";
option java_outer_classname = "ExtAuthzProto";
option java_multiple_files = true;
option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/udp/udp_proxy/session/ext_authz/v3;ext_authzv3";
option (udpa.annotations.file_status).package_version_status = ACTIVE;

// [#protodoc-title: UDP session external authorization]
// UDP proxy session external authorization
// :ref:`configuration overview <config_udp_session_filters_ext_authz>`.
// [#extension: envoy.filters.udp.session.ext_authz]

// External authorization for UDP proxy sessions over the gRPC
// :ref:`CheckRequest <envoy_v3_api_msg_service.auth.v3.CheckRequest>` API.
message FilterConfig {
// Configuration for UDP datagrams buffering while the authorization call is in flight.
message BufferOptions {
// If set, the filter will only buffer datagrams up to the requested limit, and will drop
// new UDP datagrams if the buffer contains the max_buffered_datagrams value at the time
// of a new datagram arrival. If not set, the default value is 1024 datagrams.
google.protobuf.UInt32Value max_buffered_datagrams = 1;

// If set, the filter will only buffer datagrams up to the requested total buffered bytes limit,
// and will drop new UDP datagrams if the buffer contains the max_buffered_bytes value
// at the time of a new datagram arrival. If not set, the default value is 16,384 (16KB).
google.protobuf.UInt64Value max_buffered_bytes = 2;
}

// The prefix to use when emitting :ref:`statistics
// <config_udp_session_filters_ext_authz_stats>`.
string stat_prefix = 1 [(validate.rules).string = {min_len: 1}];

// The external authorization gRPC service configuration (default timeout: 200ms).
config.core.v3.GrpcService grpc_service = 2 [(validate.rules).message = {required: true}];

// The filter's behaviour in case the external authorization service does not respond back, or
// when it returns an error. When set to true, the new session is established and traffic is
// forwarded to the upstream. When set to false, the session is dropped. Defaults to false.
bool failure_mode_allow = 3;

// If configured, the filter will buffer datagrams while it is waiting for the authorization
// response. If this field is not configured, there will be no buffering and downstream datagrams
// that arrive while the authorization call is in progress will be dropped. In case this field is
// set but the options are not configured, the default values will be applied as described in the
// ``BufferOptions``.
BufferOptions buffer_options = 4;
}
1 change: 1 addition & 0 deletions api/versioning/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ proto_library(
"//envoy/extensions/filters/udp/dns_filter/v3:pkg",
"//envoy/extensions/filters/udp/dynamic_modules/v3:pkg",
"//envoy/extensions/filters/udp/udp_proxy/session/dynamic_forward_proxy/v3:pkg",
"//envoy/extensions/filters/udp/udp_proxy/session/ext_authz/v3:pkg",
"//envoy/extensions/filters/udp/udp_proxy/session/http_capsule/v3:pkg",
"//envoy/extensions/filters/udp/udp_proxy/v3:pkg",
"//envoy/extensions/formatter/cel/v3:pkg",
Expand Down
5 changes: 5 additions & 0 deletions changelogs/current.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ behavior_changes:
certificates. Configurations setting this option to ``false`` will no longer have any effect and enforcement will be used.

new_features:
- area: udp
change: |
Added a UDP proxy session filter :ref:`ext_authz
<envoy_v3_api_msg_extensions.filters.udp.udp_proxy.session.ext_authz.v3.FilterConfig>` that performs
external authorization over the gRPC Authorization API when a new UDP session is established.
- area: network_ext_proc
change: |
Added support for receiving untyped dynamic metadata from the external processing server.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
.. _config_udp_session_filters_ext_authz:

External authorization
==================================

The external authorization session filter calls an external authorization service when a new UDP
session is established, to check whether the session is authorized. The session's downstream source
and destination addresses are sent as the ``source`` and ``destination`` peers of the request. If
the session is denied, it is dropped and no upstream is created.

The filter uses the gRPC Authorization API defined by
:ref:`CheckRequest <envoy_v3_api_msg_service.auth.v3.CheckRequest>`. A failed check, or an error
when :ref:`failure_mode_allow
<envoy_v3_api_field_extensions.filters.udp.udp_proxy.session.ext_authz.v3.FilterConfig.failure_mode_allow>`
is not set, causes the session to be dropped.

By default, datagrams that arrive while the authorization call is in flight are dropped. Configuring
:ref:`buffer_options
<envoy_v3_api_field_extensions.filters.udp.udp_proxy.session.ext_authz.v3.FilterConfig.buffer_options>`
enables buffering of those datagrams, which are then replayed if the session is allowed.

* This filter should be configured with the type URL ``type.googleapis.com/envoy.extensions.filters.udp.udp_proxy.session.ext_authz.v3.FilterConfig``.
* :ref:`v3 API reference <envoy_v3_api_msg_extensions.filters.udp.udp_proxy.session.ext_authz.v3.FilterConfig>`

.. _config_udp_session_filters_ext_authz_stats:

Statistics
----------

Every configured filter has statistics rooted at *udp.session.ext_authz.<stat_prefix>.*
with the following statistics:

.. csv-table::
:header: Name, Type, Description
:widths: 1, 1, 2

ok, Counter, Number of sessions allowed by the authorization service
denied, Counter, Number of sessions denied by the authorization service
error, Counter, Number of errors contacting the authorization service
failure_mode_allowed, Counter, Number of sessions allowed on error due to failure_mode_allow
total, Counter, Total number of authorization checks issued
buffer_overflow, Counter, Number of datagrams dropped while waiting for the authorization response due to the buffer being full
active, Gauge, Number of authorization checks currently in flight
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ Envoy has the following builtin UDP session filters.

session_filters/http_capsule
session_filters/dynamic_forward_proxy
session_filters/ext_authz

.. _config_udp_listener_filters_udp_proxy_tunneling_over_http:

Expand Down
1 change: 1 addition & 0 deletions source/extensions/extensions_build_config.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ EXTENSIONS = {

"envoy.filters.udp.session.http_capsule": "//source/extensions/filters/udp/udp_proxy/session_filters/http_capsule:config",
"envoy.filters.udp.session.dynamic_forward_proxy": "//source/extensions/filters/udp/udp_proxy/session_filters/dynamic_forward_proxy:config",
"envoy.filters.udp.session.ext_authz": "//source/extensions/filters/udp/udp_proxy/session_filters/ext_authz:config",

#
# Resource monitors
Expand Down
7 changes: 7 additions & 0 deletions source/extensions/extensions_metadata.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1059,6 +1059,13 @@ envoy.filters.udp.session.dynamic_forward_proxy:
status: alpha
type_urls:
- envoy.extensions.filters.udp.udp_proxy.session.dynamic_forward_proxy.v3.FilterConfig
envoy.filters.udp.session.ext_authz:
categories:
- envoy.filters.udp.session
security_posture: robust_to_untrusted_downstream
status: alpha
type_urls:
- envoy.extensions.filters.udp.udp_proxy.session.ext_authz.v3.FilterConfig
envoy.filters.upstream_network.reverse_tunnel_lifecycle:
categories:
- envoy.filters.upstream_network
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
load(
"//bazel:envoy_build_system.bzl",
"envoy_cc_extension",
"envoy_cc_library",
"envoy_extension_package",
)

licenses(["notice"]) # Apache 2

envoy_extension_package()

envoy_cc_library(
name = "ext_authz_lib",
srcs = ["ext_authz.cc"],
hdrs = ["ext_authz.h"],
deps = [
"//envoy/grpc:async_client_manager_interface",
"//envoy/network:filter_interface",
"//envoy/server:factory_context_interface",
"//envoy/stats:stats_macros",
"//envoy/upstream:cluster_manager_interface",
"//source/common/common:logger_lib",
"//source/common/network:utility_lib",
"//source/common/protobuf:utility_lib",
"//source/common/tracing:null_span_lib",
"//source/extensions/filters/common/ext_authz:ext_authz_grpc_lib",
"//source/extensions/filters/common/ext_authz:ext_authz_interface",
"@envoy_api//envoy/config/core/v3:pkg_cc_proto",
"@envoy_api//envoy/extensions/filters/udp/udp_proxy/session/ext_authz/v3:pkg_cc_proto",
"@envoy_api//envoy/service/auth/v3:pkg_cc_proto",
],
)

envoy_cc_extension(
name = "config",
srcs = ["config.cc"],
hdrs = ["config.h"],
deps = [
":ext_authz_lib",
"//envoy/registry",
"//source/extensions/filters/udp/udp_proxy/session_filters:factory_base_lib",
"@envoy_api//envoy/extensions/filters/udp/udp_proxy/session/ext_authz/v3:pkg_cc_proto",
],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#include "source/extensions/filters/udp/udp_proxy/session_filters/ext_authz/config.h"

#include "envoy/registry/registry.h"
#include "envoy/server/filter_config.h"

#include "source/extensions/filters/udp/udp_proxy/session_filters/ext_authz/ext_authz.h"

namespace Envoy {
namespace Extensions {
namespace UdpFilters {
namespace UdpProxy {
namespace SessionFilters {
namespace ExtAuthz {

ExtAuthzFilterConfigFactory::ExtAuthzFilterConfigFactory()
: FactoryBase("envoy.filters.udp.session.ext_authz") {}

FilterFactoryCb ExtAuthzFilterConfigFactory::createFilterFactoryFromProtoTyped(
const FilterConfig& proto_config, Server::Configuration::FactoryContext& context) {
ConfigSharedPtr filter_config =
std::make_shared<Config>(proto_config, context.scope(), context.serverFactoryContext());

return [filter_config](Network::UdpSessionFilterChainFactoryCallbacks& callbacks) -> void {
callbacks.addReadFilter(std::make_shared<Filter>(filter_config, filter_config->createClient()));
};
}

/**
* Static registration for the UDP session ext_authz filter. @see RegisterFactory.
*/
REGISTER_FACTORY(ExtAuthzFilterConfigFactory, NamedUdpSessionFilterConfigFactory);

} // namespace ExtAuthz
} // namespace SessionFilters
} // namespace UdpProxy
} // namespace UdpFilters
} // namespace Extensions
} // namespace Envoy
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#pragma once

#include "envoy/extensions/filters/udp/udp_proxy/session/ext_authz/v3/ext_authz.pb.h"
#include "envoy/extensions/filters/udp/udp_proxy/session/ext_authz/v3/ext_authz.pb.validate.h"

#include "source/extensions/filters/udp/udp_proxy/session_filters/factory_base.h"

namespace Envoy {
namespace Extensions {
namespace UdpFilters {
namespace UdpProxy {
namespace SessionFilters {
namespace ExtAuthz {

using FilterConfig =
envoy::extensions::filters::udp::udp_proxy::session::ext_authz::v3::FilterConfig;
using FilterFactoryCb = Network::UdpSessionFilterFactoryCb;

/**
* Config registration for the UDP session ext_authz filter. @see
* NamedUdpSessionFilterConfigFactory.
*/
class ExtAuthzFilterConfigFactory : public FactoryBase<FilterConfig> {
public:
ExtAuthzFilterConfigFactory();

private:
FilterFactoryCb
createFilterFactoryFromProtoTyped(const FilterConfig& proto_config,
Server::Configuration::FactoryContext& context) override;
};

} // namespace ExtAuthz
} // namespace SessionFilters
} // namespace UdpProxy
} // namespace UdpFilters
} // namespace Extensions
} // namespace Envoy
Loading
Loading