mirror of
https://github.com/pomerium/pomerium.git
synced 2025-04-30 10:56:28 +02:00
config: add support for codec_type (#2156)
* config: add support for codec_type * add comma * fix warning block * fix docs
This commit is contained in:
parent
0adbf4f24c
commit
699ebf061a
9 changed files with 838 additions and 646 deletions
75
config/codec_type.go
Normal file
75
config/codec_type.go
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
envoy_http_connection_manager "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3"
|
||||||
|
"github.com/mitchellh/mapstructure"
|
||||||
|
)
|
||||||
|
|
||||||
|
// The CodecType specifies which codec to use for downstream connections.
|
||||||
|
type CodecType string
|
||||||
|
|
||||||
|
// CodecTypes
|
||||||
|
const (
|
||||||
|
CodecTypeAuto CodecType = "auto"
|
||||||
|
CodecTypeHTTP1 CodecType = "http1"
|
||||||
|
CodecTypeHTTP2 CodecType = "http2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ParseCodecType parses the codec type.
|
||||||
|
func ParseCodecType(raw string) (CodecType, error) {
|
||||||
|
switch CodecType(strings.TrimSpace(strings.ToLower(raw))) {
|
||||||
|
case CodecTypeAuto:
|
||||||
|
return CodecTypeAuto, nil
|
||||||
|
case CodecTypeHTTP1:
|
||||||
|
return CodecTypeHTTP1, nil
|
||||||
|
case CodecTypeHTTP2:
|
||||||
|
return CodecTypeHTTP2, nil
|
||||||
|
}
|
||||||
|
return CodecTypeAuto, fmt.Errorf("invalid codec type: %s", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CodecTypeFromEnvoy converts an envoy codec type into a config codec type.
|
||||||
|
func CodecTypeFromEnvoy(envoyCodecType envoy_http_connection_manager.HttpConnectionManager_CodecType) CodecType {
|
||||||
|
switch envoyCodecType {
|
||||||
|
case envoy_http_connection_manager.HttpConnectionManager_HTTP1:
|
||||||
|
return CodecTypeHTTP1
|
||||||
|
case envoy_http_connection_manager.HttpConnectionManager_HTTP2:
|
||||||
|
return CodecTypeHTTP2
|
||||||
|
}
|
||||||
|
return CodecTypeAuto
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToEnvoy converts the codec type to an envoy codec type.
|
||||||
|
func (codecType CodecType) ToEnvoy() envoy_http_connection_manager.HttpConnectionManager_CodecType {
|
||||||
|
switch codecType {
|
||||||
|
case CodecTypeHTTP1:
|
||||||
|
return envoy_http_connection_manager.HttpConnectionManager_HTTP1
|
||||||
|
case CodecTypeHTTP2:
|
||||||
|
return envoy_http_connection_manager.HttpConnectionManager_HTTP2
|
||||||
|
}
|
||||||
|
return envoy_http_connection_manager.HttpConnectionManager_AUTO
|
||||||
|
}
|
||||||
|
|
||||||
|
func decodeCodecTypeHookFunc() mapstructure.DecodeHookFunc {
|
||||||
|
return func(f, t reflect.Type, data interface{}) (interface{}, error) {
|
||||||
|
if t != reflect.TypeOf(CodecType("")) {
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
bs, err := json.Marshal(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var raw string
|
||||||
|
err = json.Unmarshal(bs, &raw)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ParseCodecType(raw)
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,14 +23,10 @@ var (
|
||||||
errEitherToOrRedirectRequired = errors.New("policy should have either `to` or `redirect` defined")
|
errEitherToOrRedirectRequired = errors.New("policy should have either `to` or `redirect` defined")
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var protoPartial = protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true}
|
||||||
protoPartial = protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true}
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
|
|
||||||
// ViperPolicyHooks are used to decode options and policy coming from YAML and env vars
|
// ViperPolicyHooks are used to decode options and policy coming from YAML and env vars
|
||||||
ViperPolicyHooks = viper.DecodeHook(mapstructure.ComposeDecodeHookFunc(
|
var ViperPolicyHooks = viper.DecodeHook(mapstructure.ComposeDecodeHookFunc(
|
||||||
mapstructure.StringToTimeDurationHookFunc(),
|
mapstructure.StringToTimeDurationHookFunc(),
|
||||||
mapstructure.StringToSliceHookFunc(","),
|
mapstructure.StringToSliceHookFunc(","),
|
||||||
// decode policy including all protobuf-native notations - i.e. duration as `1s`
|
// decode policy including all protobuf-native notations - i.e. duration as `1s`
|
||||||
|
@ -39,5 +35,5 @@ var (
|
||||||
// parse base-64 encoded POLICY that is bound to environment variable
|
// parse base-64 encoded POLICY that is bound to environment variable
|
||||||
DecodePolicyBase64Hook(),
|
DecodePolicyBase64Hook(),
|
||||||
decodeJWTClaimHeadersHookFunc(),
|
decodeJWTClaimHeadersHookFunc(),
|
||||||
|
decodeCodecTypeHookFunc(),
|
||||||
))
|
))
|
||||||
)
|
|
||||||
|
|
|
@ -453,7 +453,7 @@ func (b *Builder) buildMainHTTPConnectionManagerFilter(
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
tc := marshalAny(&envoy_http_connection_manager.HttpConnectionManager{
|
tc := marshalAny(&envoy_http_connection_manager.HttpConnectionManager{
|
||||||
CodecType: envoy_http_connection_manager.HttpConnectionManager_AUTO,
|
CodecType: options.GetCodecType().ToEnvoy(),
|
||||||
StatPrefix: "ingress",
|
StatPrefix: "ingress",
|
||||||
RouteSpecifier: &envoy_http_connection_manager.HttpConnectionManager_RouteConfig{
|
RouteSpecifier: &envoy_http_connection_manager.HttpConnectionManager_RouteConfig{
|
||||||
RouteConfig: rc,
|
RouteConfig: rc,
|
||||||
|
|
|
@ -290,6 +290,9 @@ type Options struct {
|
||||||
// ProgrammaticRedirectDomainWhitelist restricts the allowed redirect URLs when using programmatic login.
|
// ProgrammaticRedirectDomainWhitelist restricts the allowed redirect URLs when using programmatic login.
|
||||||
ProgrammaticRedirectDomainWhitelist []string `mapstructure:"programmatic_redirect_domain_whitelist" yaml:"programmatic_redirect_domain_whitelist,omitempty" json:"programmatic_redirect_domain_whitelist,omitempty"` //nolint
|
ProgrammaticRedirectDomainWhitelist []string `mapstructure:"programmatic_redirect_domain_whitelist" yaml:"programmatic_redirect_domain_whitelist,omitempty" json:"programmatic_redirect_domain_whitelist,omitempty"` //nolint
|
||||||
|
|
||||||
|
// CodecType is the codec to use for downstream connections.
|
||||||
|
CodecType CodecType `mapstructure:"codec_type" yaml:"codec_type"`
|
||||||
|
|
||||||
AuditKey *PublicKeyEncryptionKeyOptions `mapstructure:"audit_key"`
|
AuditKey *PublicKeyEncryptionKeyOptions `mapstructure:"audit_key"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -940,6 +943,14 @@ func (o *Options) GetQPS() float64 {
|
||||||
return o.QPS
|
return o.QPS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetCodecType gets a codec type.
|
||||||
|
func (o *Options) GetCodecType() CodecType {
|
||||||
|
if IsAll(o.Services) && o.CodecType == CodecTypeAuto {
|
||||||
|
return CodecTypeHTTP1
|
||||||
|
}
|
||||||
|
return o.CodecType
|
||||||
|
}
|
||||||
|
|
||||||
// Checksum returns the checksum of the current options struct
|
// Checksum returns the checksum of the current options struct
|
||||||
func (o *Options) Checksum() uint64 {
|
func (o *Options) Checksum() uint64 {
|
||||||
return hashutil.MustHash(o)
|
return hashutil.MustHash(o)
|
||||||
|
@ -1177,6 +1188,9 @@ func (o *Options) ApplySettings(settings *config.Settings) {
|
||||||
Data: base64.StdEncoding.EncodeToString(settings.AuditKey.GetData()),
|
Data: base64.StdEncoding.EncodeToString(settings.AuditKey.GetData()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if settings.CodecType != nil {
|
||||||
|
o.CodecType = CodecTypeFromEnvoy(settings.GetCodecType())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func dataDir() string {
|
func dataDir() string {
|
||||||
|
|
|
@ -926,6 +926,40 @@ Do not append proxy IP address to `x-forwarded-for` HTTP header. See [Envoy](htt
|
||||||
The number of trusted reverse proxies in front of pomerium. This affects `x-forwarded-proto` header and [`x-envoy-external-address` header](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_man/headers#x-envoy-external-address), which reports tursted client address. [Envoy](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_man/headers.html?highlight=xff_num_trusted_hops#x-forwarded-for) docs for more detail.
|
The number of trusted reverse proxies in front of pomerium. This affects `x-forwarded-proto` header and [`x-envoy-external-address` header](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_man/headers#x-envoy-external-address), which reports tursted client address. [Envoy](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_man/headers.html?highlight=xff_num_trusted_hops#x-forwarded-for) docs for more detail.
|
||||||
|
|
||||||
|
|
||||||
|
### Codec Type
|
||||||
|
- Environment Variable: `CODEC_TYPE`
|
||||||
|
- Config File Key: `codec_type`
|
||||||
|
- Type: `string`
|
||||||
|
- Default: `auto` (`http1` in all-in-one mode)
|
||||||
|
|
||||||
|
Specifies the codec to use for downstream connections. Either `auto`, `http1` or `http2`.
|
||||||
|
|
||||||
|
When `auto` is specified the codec will be determined via TLS ALPN or protocol inference.
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
|
||||||
|
With HTTP/2, browsers typically coalesce connections for the same IP address that use the same
|
||||||
|
TLS certificate. For example, you may have `authenticate.localhost.pomerium.io` and
|
||||||
|
`example.localhost.pomerium.io` using the same wildcard certificate (`*.localhost.pomerium.io`)
|
||||||
|
and both pointing to `127.0.0.1`. Your browser sees this and re-uses the initial connection
|
||||||
|
it makes to `example` for `authenticate`. But unfortunately the routes necessary to handle
|
||||||
|
`authenticate` don't exist on `example` so the proxy cannot handle the request.
|
||||||
|
|
||||||
|
If this happens Pomerium will respond with a `421 Misdirected Request` status. Most browsers will attempt to
|
||||||
|
make the request on a new HTTP/2 connection. However not all browsers implement this behavior
|
||||||
|
(notably Safari), and users may end up seeing a blank page instead.
|
||||||
|
|
||||||
|
If you see this happen, there are several ways to mitigate the problem:
|
||||||
|
|
||||||
|
1. Don't re-use TLS certificates for shared IP domains.
|
||||||
|
2. Don't re-use IP addresses for shared TLS certificates.
|
||||||
|
3. Don't use HTTP/2.
|
||||||
|
|
||||||
|
More details on this problem are available in [Github Issue #2150](https://github.com/pomerium/pomerium/issues/2150).
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
|
||||||
## Data Broker Service
|
## Data Broker Service
|
||||||
The databroker service is used for storing user session data.
|
The databroker service is used for storing user session data.
|
||||||
|
|
||||||
|
|
|
@ -1046,6 +1046,40 @@ settings:
|
||||||
The number of trusted reverse proxies in front of pomerium. This affects `x-forwarded-proto` header and [`x-envoy-external-address` header](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_man/headers#x-envoy-external-address), which reports tursted client address. [Envoy](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_man/headers.html?highlight=xff_num_trusted_hops#x-forwarded-for) docs for more detail.
|
The number of trusted reverse proxies in front of pomerium. This affects `x-forwarded-proto` header and [`x-envoy-external-address` header](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_man/headers#x-envoy-external-address), which reports tursted client address. [Envoy](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_man/headers.html?highlight=xff_num_trusted_hops#x-forwarded-for) docs for more detail.
|
||||||
shortdoc: |
|
shortdoc: |
|
||||||
The number of trusted reverse proxies in front of pomerium.
|
The number of trusted reverse proxies in front of pomerium.
|
||||||
|
- name: "Codec Type"
|
||||||
|
keys: ["codec_type"]
|
||||||
|
attributes: |
|
||||||
|
- Environment Variable: `CODEC_TYPE`
|
||||||
|
- Config File Key: `codec_type`
|
||||||
|
- Type: `string`
|
||||||
|
- Default: `auto` (`http1` in all-in-one mode)
|
||||||
|
doc: |
|
||||||
|
Specifies the codec to use for downstream connections. Either `auto`, `http1` or `http2`.
|
||||||
|
|
||||||
|
When `auto` is specified the codec will be determined via TLS ALPN or protocol inference.
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
|
||||||
|
With HTTP/2, browsers typically coalesce connections for the same IP address that use the same
|
||||||
|
TLS certificate. For example, you may have `authenticate.localhost.pomerium.io` and
|
||||||
|
`example.localhost.pomerium.io` using the same wildcard certificate (`*.localhost.pomerium.io`)
|
||||||
|
and both pointing to `127.0.0.1`. Your browser sees this and re-uses the initial connection
|
||||||
|
it makes to `example` for `authenticate`. But unfortunately the routes necessary to handle
|
||||||
|
`authenticate` don't exist on `example` so the proxy cannot handle the request.
|
||||||
|
|
||||||
|
If this happens Pomerium will respond with a `421 Misdirected Request` status. Most browsers will attempt to
|
||||||
|
make the request on a new HTTP/2 connection. However not all browsers implement this behavior
|
||||||
|
(notably Safari), and users may end up seeing a blank page instead.
|
||||||
|
|
||||||
|
If you see this happen, there are several ways to mitigate the problem:
|
||||||
|
|
||||||
|
1. Don't re-use TLS certificates for shared IP domains.
|
||||||
|
2. Don't re-use IP addresses for shared TLS certificates.
|
||||||
|
3. Don't use HTTP/2.
|
||||||
|
|
||||||
|
More details on this problem are available in [Github Issue #2150](https://github.com/pomerium/pomerium/issues/2150).
|
||||||
|
|
||||||
|
:::
|
||||||
- name: "Data Broker Service"
|
- name: "Data Broker Service"
|
||||||
doc: |
|
doc: |
|
||||||
The databroker service is used for storing user session data.
|
The databroker service is used for storing user session data.
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -8,6 +8,7 @@ import "google/protobuf/duration.proto";
|
||||||
import "google/protobuf/struct.proto";
|
import "google/protobuf/struct.proto";
|
||||||
import "google/protobuf/timestamp.proto";
|
import "google/protobuf/timestamp.proto";
|
||||||
import "envoy/config/cluster/v3/cluster.proto";
|
import "envoy/config/cluster/v3/cluster.proto";
|
||||||
|
import "envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto";
|
||||||
|
|
||||||
import "crypt/crypt.proto";
|
import "crypt/crypt.proto";
|
||||||
|
|
||||||
|
@ -183,6 +184,8 @@ message Settings {
|
||||||
optional uint32 xff_num_trusted_hops = 70;
|
optional uint32 xff_num_trusted_hops = 70;
|
||||||
repeated string programmatic_redirect_domain_whitelist = 68;
|
repeated string programmatic_redirect_domain_whitelist = 68;
|
||||||
optional pomerium.crypt.PublicKeyEncryptionKey audit_key = 72;
|
optional pomerium.crypt.PublicKeyEncryptionKey audit_key = 72;
|
||||||
|
optional envoy.extensions.filters.network.http_connection_manager.v3
|
||||||
|
.HttpConnectionManager.CodecType codec_type = 73;
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnvoyConfigurationEvents is a list of envoy configuration events.
|
// EnvoyConfigurationEvents is a list of envoy configuration events.
|
||||||
|
|
|
@ -8,6 +8,7 @@ function join_by() {
|
||||||
|
|
||||||
_protos=(
|
_protos=(
|
||||||
"envoy/annotations/deprecation.proto"
|
"envoy/annotations/deprecation.proto"
|
||||||
|
"envoy/config/accesslog/v3/accesslog.proto"
|
||||||
"envoy/config/cluster/v3/circuit_breaker.proto"
|
"envoy/config/cluster/v3/circuit_breaker.proto"
|
||||||
"envoy/config/cluster/v3/cluster.proto"
|
"envoy/config/cluster/v3/cluster.proto"
|
||||||
"envoy/config/cluster/v3/filter.proto"
|
"envoy/config/cluster/v3/filter.proto"
|
||||||
|
@ -24,17 +25,26 @@ _protos=(
|
||||||
"envoy/config/core/v3/protocol.proto"
|
"envoy/config/core/v3/protocol.proto"
|
||||||
"envoy/config/core/v3/proxy_protocol.proto"
|
"envoy/config/core/v3/proxy_protocol.proto"
|
||||||
"envoy/config/core/v3/socket_option.proto"
|
"envoy/config/core/v3/socket_option.proto"
|
||||||
|
"envoy/config/core/v3/substitution_format_string.proto"
|
||||||
"envoy/config/endpoint/v3/endpoint_components.proto"
|
"envoy/config/endpoint/v3/endpoint_components.proto"
|
||||||
"envoy/config/endpoint/v3/endpoint.proto"
|
"envoy/config/endpoint/v3/endpoint.proto"
|
||||||
"envoy/config/route/v3/route_components.proto"
|
"envoy/config/route/v3/route_components.proto"
|
||||||
|
"envoy/config/route/v3/route.proto"
|
||||||
|
"envoy/config/route/v3/scoped_route.proto"
|
||||||
|
"envoy/config/trace/v3/http_tracer.proto"
|
||||||
|
"envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto"
|
||||||
"envoy/service/auth/v3/attribute_context.proto"
|
"envoy/service/auth/v3/attribute_context.proto"
|
||||||
"envoy/service/auth/v3/external_auth.proto"
|
"envoy/service/auth/v3/external_auth.proto"
|
||||||
|
"envoy/type/http/v3/path_transformation.proto"
|
||||||
|
"envoy/type/matcher/v3/metadata.proto"
|
||||||
|
"envoy/type/matcher/v3/number.proto"
|
||||||
"envoy/type/matcher/v3/regex.proto"
|
"envoy/type/matcher/v3/regex.proto"
|
||||||
"envoy/type/matcher/v3/string.proto"
|
"envoy/type/matcher/v3/string.proto"
|
||||||
|
"envoy/type/matcher/v3/value.proto"
|
||||||
"envoy/type/metadata/v3/metadata.proto"
|
"envoy/type/metadata/v3/metadata.proto"
|
||||||
"envoy/type/tracing/v3/custom_tag.proto"
|
"envoy/type/tracing/v3/custom_tag.proto"
|
||||||
"envoy/type/v3/http.proto"
|
|
||||||
"envoy/type/v3/http_status.proto"
|
"envoy/type/v3/http_status.proto"
|
||||||
|
"envoy/type/v3/http.proto"
|
||||||
"envoy/type/v3/percent.proto"
|
"envoy/type/v3/percent.proto"
|
||||||
"envoy/type/v3/range.proto"
|
"envoy/type/v3/range.proto"
|
||||||
"envoy/type/v3/semantic_version.proto"
|
"envoy/type/v3/semantic_version.proto"
|
||||||
|
|
Loading…
Add table
Reference in a new issue