Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
c842511
Add SXG filter extension
Jun 16, 2021
ed6ab85
spelling, formatting fixes
Jul 2, 2021
379c171
fix docs, deps
Jul 2, 2021
b35530e
formatting
Jul 2, 2021
a0b9d37
formatting, deps
Jul 2, 2021
a0df7eb
formatting
Jul 2, 2021
f7f94f3
formatting
Jul 2, 2021
d987065
dont hardcode x-envoy-
Jul 2, 2021
1cdc3fe
replace regex with plain string operations
Jul 4, 2021
a34b7ce
set a maintainer in codeowners
Jul 4, 2021
408f8ba
clang-tidy
Jul 5, 2021
8d91b28
clang-tidy
Jul 5, 2021
176da33
add config tests, fix coverage issues in filter test
Jul 7, 2021
6a682cc
mock sxg functions to test error cases
Jul 7, 2021
63d4e77
fix coverage
Jul 7, 2021
ffe9096
bump libsxg version
Jul 7, 2021
2475eba
bump libsxg version to support old cmake
Jul 8, 2021
5a075c0
fix off-by-one in libsxg release date
Jul 8, 2021
3013808
set CMAKE_TRY_COMPILE_TARGET_TYPE to avoid errors during asan build (…
Jul 9, 2021
cb42fb3
set resource_api_version in config_test, disable tests for windows
Jul 9, 2021
899f9af
move libsxg library build to external
Jul 9, 2021
ed2a76a
code format
Jul 9, 2021
7290003
specify external deps
Jul 10, 2021
a300402
specify external deps
Jul 10, 2021
a399fae
specify external deps
Jul 10, 2021
3d24487
specify in WINDOWS_SKIP_TARGETS
Jul 12, 2021
da08688
fix WINDOWS_SKIP_TARGETS
Jul 13, 2021
52e38af
fix test targets after rebase
Jul 13, 2021
109f681
retest
Jul 13, 2021
62edc01
fix/improve proto comments
Jul 16, 2021
8e3e105
update proto comments per code review
Jul 19, 2021
28d810f
code review and docs
Jul 19, 2021
a8527fc
proto config validation
Jul 19, 2021
4b31ce7
Merge remote-tracking branch 'upstream/main' into sxg_filter_2
Jul 21, 2021
9041a96
use min_len instead of min_bytes for proto validation
Jul 21, 2021
98ac0a3
improve proto docs, add links to rst docs
Jul 22, 2021
a442e35
fix indendation in docs
Jul 22, 2021
e10417a
fix windows not supported docs
Jul 26, 2021
b5a3974
wrap sxg_buffer_t contents in BufferFragmentImpl, rather than copy
Jul 27, 2021
35bbb75
create encoder class to encapsulate sxg logic
Jul 28, 2021
f04525a
sxg_signer_list_release
Jul 28, 2021
5d8eec4
Merge remote-tracking branch 'upstream/main' into sxg_filter_2
Jul 28, 2021
b546ef7
fix tests
Jul 28, 2021
7882a4c
fix formatting
Jul 28, 2021
70fd30c
formatting
Jul 28, 2021
0344275
Merge remote-tracking branch 'upstream/main' into sxg_filter_2
Jul 28, 2021
c820230
switch encoder to unique_ptr
Jul 28, 2021
d3a92b7
fotmatting
Jul 28, 2021
3b5855c
delete buffer fragment
Jul 29, 2021
99c8138
free buffer ragment when size limit is reached
Jul 29, 2021
4739cc7
add comments, improve test coverage
Jul 29, 2021
acfeecf
spelling
Jul 29, 2021
439ccfa
retest
Jul 29, 2021
ecaaa15
retest
Jul 30, 2021
c008afe
Merge remote-tracking branch 'upstream/main' into sxg_filter_2
Jul 30, 2021
34f34f1
dry up tests
Jul 30, 2021
12a5abb
formatting
Jul 30, 2021
d99f6bd
formatting
Jul 30, 2021
d973930
Merge remote-tracking branch 'upstream/main' into sxg_filter_2
Aug 9, 2021
e91d901
fix order
Aug 9, 2021
f97fe19
Merge remote-tracking branch 'upstream/main' into sxg_filter_2
Aug 9, 2021
0f7677a
retest
Aug 9, 2021
76cad54
Merge remote-tracking branch 'upstream/main' into sxg_filter_2
Aug 30, 2021
27aa2e2
fix ordering
Aug 30, 2021
99a0683
move sxg filter to contrib
Aug 30, 2021
4c176d1
move sxg filter to contrib
Aug 31, 2021
30c1ab6
formatting
Aug 31, 2021
9bf9892
note contrib
Sep 1, 2021
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 @@ -202,3 +202,4 @@ extensions/filters/http/oauth2 @rgs1 @derekargueta @snowp
/contrib/rocketmq_proxy/ @aaron-ai @lizhanhui @lizan
/contrib/mysql_proxy/ @rshriram @venilnoronha
/contrib/postgres_proxy/ @fabriziomello @cpakulski @dio
/contrib/sxg/ @cpapazian @rgs1 @alyssawilk
1 change: 1 addition & 0 deletions api/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ proto_library(
visibility = ["//visibility:public"],
deps = [
"//contrib/envoy/extensions/filters/http/squash/v3:pkg",
"//contrib/envoy/extensions/filters/http/sxg/v3alpha:pkg",
"//contrib/envoy/extensions/filters/network/kafka_broker/v3:pkg",
"//contrib/envoy/extensions/filters/network/mysql_proxy/v3:pkg",
"//contrib/envoy/extensions/filters/network/postgres_proxy/v3alpha:pkg",
Expand Down
12 changes: 12 additions & 0 deletions api/contrib/envoy/extensions/filters/http/sxg/v3alpha/BUILD
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/extensions/transport_sockets/tls/v3:pkg",
"@com_github_cncf_udpa//udpa/annotations:pkg",
],
)
67 changes: 67 additions & 0 deletions api/contrib/envoy/extensions/filters/http/sxg/v3alpha/sxg.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
syntax = "proto3";

package envoy.extensions.filters.http.sxg.v3alpha;

import "envoy/extensions/transport_sockets/tls/v3/secret.proto";

import "google/protobuf/duration.proto";

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

option java_package = "io.envoyproxy.envoy.extensions.filters.http.sxg.v3alpha";
option java_outer_classname = "SxgProto";
option java_multiple_files = true;
option (udpa.annotations.file_status).work_in_progress = true;
option (udpa.annotations.file_status).package_version_status = ACTIVE;

// [#protodoc-title: Signed HTTP Exchange Filter]
// SXG :ref:`configuration overview <config_http_filters_sxg>`.
// [#extension: envoy.filters.http.sxg]

// [#next-free-field: 10]
message SXG {
// The SDS configuration for the public key data for the SSL certificate that will be used to sign the
// SXG response.
transport_sockets.tls.v3.SdsSecretConfig certificate = 1;

// The SDS configuration for the private key data for the SSL certificate that will be used to sign the
// SXG response.
transport_sockets.tls.v3.SdsSecretConfig private_key = 2;

// The duration for which the generated SXG package will be valid. Default is 604800s (7 days in seconds).
// Note that in order to account for clock skew, the timestamp will be backdated by a day. So, if duration
// is set to 7 days, that will be 7 days from 24 hours ago (6 days from now). Also note that while 6/7 days
// is appropriate for most content, if the downstream service is serving Javascript, or HTML with inline
// Javascript, 1 day (so, with backdated expiry, 2 days, or 172800 seconds) is more appropriate.
google.protobuf.Duration duration = 3;

// The SXG response payload is Merkle Integrity Content Encoding (MICE) encoded (specification is [here](https://datatracker.ietf.org/doc/html/draft-thomson-http-mice-03))
// This value indicates the record size in the encoded payload. The default value is 4096.
uint64 mi_record_size = 4;

// The URI of certificate CBOR file published. Since it is required that the certificate CBOR file
// be served from the same domain as the SXG document, this should be a relative URI.
string cbor_url = 5 [(validate.rules).string = {min_len: 1 prefix: "/"}];

// URL to retrieve validity data for signature, a CBOR map. See specification [here](https://tools.ietf.org/html/draft-yasskin-httpbis-origin-signed-exchanges-impl-00#section-3.6)
string validity_url = 6 [(validate.rules).string = {min_len: 1 prefix: "/"}];

// Header that will be set if it is determined that the client can accept SXG (typically `accept: application/signed-exchange;v=b3)
// If not set, filter will default to: `x-client-can-accept-sxg`
string client_can_accept_sxg_header = 7 [
(validate.rules).string = {well_known_regex: HTTP_HEADER_NAME strict: false ignore_empty: true}
];

// Header set by downstream service to signal that the response should be transformed to SXG If not set,
// filter will default to: `x-should-encode-sxg`
string should_encode_sxg_header = 8 [
(validate.rules).string = {well_known_regex: HTTP_HEADER_NAME strict: false ignore_empty: true}
];

// Headers that will be stripped from the SXG document, by listing a prefix (i.e. `x-custom-` will cause
// all headers prefixed by `x-custom-` to be omitted from the SXG document)
repeated string header_prefix_filters = 9 [
(validate.rules).repeated = {items {string {well_known_regex: HTTP_HEADER_NAME strict: false}}}
];
}
1 change: 1 addition & 0 deletions api/versioning/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ proto_library(
visibility = ["//visibility:public"],
deps = [
"//contrib/envoy/extensions/filters/http/squash/v3:pkg",
"//contrib/envoy/extensions/filters/http/sxg/v3alpha:pkg",
"//contrib/envoy/extensions/filters/network/kafka_broker/v3:pkg",
"//contrib/envoy/extensions/filters/network/mysql_proxy/v3:pkg",
"//contrib/envoy/extensions/filters/network/postgres_proxy/v3alpha:pkg",
Expand Down
18 changes: 18 additions & 0 deletions bazel/foreign_cc/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,24 @@ configure_make(
tags = ["skip_on_windows"],
)

envoy_cmake_external(
name = "libsxg",
cache_entries = {
"CMAKE_BUILD_TYPE": "Release",
"SXG_BUILD_EXECUTABLES": "off",
"SXG_BUILD_SHARED": "off",
"SXG_BUILD_STATIC": "on",
"SXG_WITH_CERT_CHAIN": "off",
"RUN_TEST": "off",
"CMAKE_INSTALL_LIBDIR": "lib",
"CMAKE_TRY_COMPILE_TARGET_TYPE": "STATIC_LIBRARY",
},
lib_source = "@com_github_google_libsxg//:all",
static_libraries = ["libsxg.a"],
tags = ["skip_on_windows"],
deps = ["@boringssl//:ssl"],
)

envoy_cmake_external(
name = "ares",
cache_entries = {
Expand Down
13 changes: 13 additions & 0 deletions bazel/repositories.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ load("@com_google_googleapis//:repository_rules.bzl", "switched_rules_by_languag
PPC_SKIP_TARGETS = ["envoy.filters.http.lua"]

WINDOWS_SKIP_TARGETS = [
"envoy.filters.http.sxg",
"envoy.tracers.dynamic_ot",
"envoy.tracers.lightstep",
"envoy.tracers.datadog",
Expand Down Expand Up @@ -134,6 +135,7 @@ def envoy_dependencies(skip_targets = []):
_com_github_google_benchmark()
_com_github_google_jwt_verify()
_com_github_google_libprotobuf_mutator()
_com_github_google_libsxg()
_com_github_google_tcmalloc()
_com_github_gperftools_gperftools()
_com_github_grpc_grpc()
Expand Down Expand Up @@ -312,6 +314,17 @@ def _com_github_google_libprotobuf_mutator():
build_file = "@envoy//bazel/external:libprotobuf_mutator.BUILD",
)

def _com_github_google_libsxg():
external_http_archive(
name = "com_github_google_libsxg",
build_file_content = BUILD_ALL_CONTENT,
)

native.bind(
name = "libsxg",
actual = "@envoy//bazel/foreign_cc:libsxg",
)

def _com_github_jbeder_yaml_cpp():
external_http_archive(
name = "com_github_jbeder_yaml_cpp",
Expand Down
13 changes: 13 additions & 0 deletions bazel/repository_locations.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,19 @@ REPOSITORY_LOCATIONS_SPEC = dict(
release_date = "2020-11-13",
use_category = ["test_only"],
),
com_github_google_libsxg = dict(
project_name = "libsxg",
project_desc = "Signed HTTP Exchange library",
project_url = "https://github.com/google/libsxg",
version = "beaa3939b76f8644f6833267e9f2462760838f18",
sha256 = "082bf844047a9aeec0d388283d5edc68bd22bcf4d32eb5a566654ae89956ad1f",
strip_prefix = "libsxg-{version}",
urls = ["https://github.com/google/libsxg/archive/{version}.tar.gz"],
use_category = ["other"],
extensions = ["envoy.filters.http.sxg"],
release_date = "2021-07-08",
cpe = "N/A",
),
com_github_google_tcmalloc = dict(
project_name = "tcmalloc",
project_desc = "Fast, multi-threaded malloc implementation",
Expand Down
1 change: 1 addition & 0 deletions contrib/contrib_build_config.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ CONTRIB_EXTENSIONS = {
#

"envoy.filters.http.squash": "//contrib/squash/filters/http/source:config",
"envoy.filters.http.sxg": "//contrib/sxg/filters/http/source:config",

#
# Network filters
Expand Down
6 changes: 6 additions & 0 deletions contrib/extensions_metadata.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ envoy.filters.http.squash:
- envoy.filters.http
security_posture: requires_trusted_downstream_and_upstream
status: stable
envoy.filters.http.sxg:
categories:
- envoy.filters.http
security_posture: robust_to_untrusted_downstream
status: alpha
envoy.filters.network.kafka_broker:
categories:
- envoy.filters.network
Expand All @@ -23,3 +28,4 @@ envoy.filters.network.postgres_proxy:
- envoy.filters.network
security_posture: requires_trusted_downstream_and_upstream
status: stable

47 changes: 47 additions & 0 deletions contrib/sxg/filters/http/source/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
load(
"//bazel:envoy_build_system.bzl",
"envoy_cc_contrib_extension",
"envoy_cc_library",
"envoy_contrib_package",
)

licenses(["notice"]) # Apache 2

envoy_contrib_package()

envoy_cc_library(
name = "sxg_lib",
srcs = [
"encoder.cc",
"filter.cc",
"filter_config.cc",
],
hdrs = [
"encoder.h",
"filter.h",
"filter_config.h",
],
external_deps = ["libsxg"],
deps = [
"//envoy/server:filter_config_interface",
"//source/common/config:datasource_lib",
"//source/common/http:codes_lib",
"//source/common/stats:symbol_table_lib",
"//source/common/stats:utility_lib",
"//source/extensions/filters/http/common:pass_through_filter_lib",
"@boringssl//:ssl",
"@envoy_api//contrib/envoy/extensions/filters/http/sxg/v3alpha:pkg_cc_proto",
],
)

envoy_cc_contrib_extension(
name = "config",
srcs = ["config.cc"],
hdrs = ["config.h"],
deps = [
":sxg_lib",
"//envoy/registry",
"//source/extensions/filters/http/common:factory_base_lib",
"@envoy_api//contrib/envoy/extensions/filters/http/sxg/v3alpha:pkg_cc_proto",
],
)
71 changes: 71 additions & 0 deletions contrib/sxg/filters/http/source/config.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#include "contrib/sxg/filters/http/source/config.h"

#include <memory>
#include <string>

#include "envoy/registry/registry.h"
#include "envoy/secret/secret_manager.h"
#include "envoy/secret/secret_provider.h"

#include "source/common/protobuf/utility.h"

#include "contrib/envoy/extensions/filters/http/sxg/v3alpha/sxg.pb.h"
#include "contrib/envoy/extensions/filters/http/sxg/v3alpha/sxg.pb.validate.h"
#include "contrib/sxg/filters/http/source/encoder.h"
#include "contrib/sxg/filters/http/source/filter.h"

namespace Envoy {
namespace Extensions {
namespace HttpFilters {
namespace SXG {

namespace {
Secret::GenericSecretConfigProviderSharedPtr
secretsProvider(const envoy::extensions::transport_sockets::tls::v3::SdsSecretConfig& config,
Secret::SecretManager& secret_manager,
Server::Configuration::TransportSocketFactoryContext& transport_socket_factory) {
if (config.has_sds_config()) {
return secret_manager.findOrCreateGenericSecretProvider(config.sds_config(), config.name(),
transport_socket_factory);
} else {
return secret_manager.findStaticGenericSecretProvider(config.name());
}
}
} // namespace

Http::FilterFactoryCb FilterFactory::createFilterFactoryFromProtoTyped(
const envoy::extensions::filters::http::sxg::v3alpha::SXG& proto_config,
const std::string& stat_prefix, Server::Configuration::FactoryContext& context) {
const auto& certificate = proto_config.certificate();
const auto& private_key = proto_config.private_key();

auto& cluster_manager = context.clusterManager();
auto& secret_manager = cluster_manager.clusterManagerFactory().secretManager();
auto& transport_socket_factory = context.getTransportSocketFactoryContext();
auto secret_provider_certificate =
secretsProvider(certificate, secret_manager, transport_socket_factory);
if (secret_provider_certificate == nullptr) {
throw EnvoyException("invalid certificate secret configuration");
}
auto secret_provider_private_key =
secretsProvider(private_key, secret_manager, transport_socket_factory);
if (secret_provider_private_key == nullptr) {
throw EnvoyException("invalid private_key secret configuration");
}

auto secret_reader = std::make_shared<SDSSecretReader>(
secret_provider_certificate, secret_provider_private_key, context.api());
auto config = std::make_shared<FilterConfig>(proto_config, context.timeSource(), secret_reader,
stat_prefix, context.scope());
return [config](Http::FilterChainFactoryCallbacks& callbacks) -> void {
const EncoderPtr encoder = std::make_unique<EncoderImpl>(config);
callbacks.addStreamFilter(std::make_shared<Filter>(config, encoder));
};
}

REGISTER_FACTORY(FilterFactory, Server::Configuration::NamedHttpFilterConfigFactory);

} // namespace SXG
} // namespace HttpFilters
} // namespace Extensions
} // namespace Envoy
31 changes: 31 additions & 0 deletions contrib/sxg/filters/http/source/config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#pragma once

#include <string>

#include "source/extensions/filters/http/common/factory_base.h"

#include "contrib/envoy/extensions/filters/http/sxg/v3alpha/sxg.pb.h"
#include "contrib/envoy/extensions/filters/http/sxg/v3alpha/sxg.pb.validate.h"

namespace Envoy {
namespace Extensions {
namespace HttpFilters {
namespace SXG {

class FilterFactory : public Extensions::HttpFilters::Common::FactoryBase<
envoy::extensions::filters::http::sxg::v3alpha::SXG> {
public:
FilterFactory() : FactoryBase("envoy.filters.http.sxg") {}

private:
Http::FilterFactoryCb createFilterFactoryFromProtoTyped(
const envoy::extensions::filters::http::sxg::v3alpha::SXG& config,
const std::string& stats_prefix, Server::Configuration::FactoryContext& context) override;
};

DECLARE_FACTORY(FilterFactory);

} // namespace SXG
} // namespace HttpFilters
} // namespace Extensions
} // namespace Envoy
Loading