mirror of
https://github.com/pomerium/pomerium.git
synced 2025-04-29 02:16: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,21 +23,17 @@ var (
|
|||
errEitherToOrRedirectRequired = errors.New("policy should have either `to` or `redirect` defined")
|
||||
)
|
||||
|
||||
var (
|
||||
protoPartial = protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true}
|
||||
)
|
||||
var protoPartial = protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true}
|
||||
|
||||
var (
|
||||
|
||||
// ViperPolicyHooks are used to decode options and policy coming from YAML and env vars
|
||||
ViperPolicyHooks = viper.DecodeHook(mapstructure.ComposeDecodeHookFunc(
|
||||
mapstructure.StringToTimeDurationHookFunc(),
|
||||
mapstructure.StringToSliceHookFunc(","),
|
||||
// decode policy including all protobuf-native notations - i.e. duration as `1s`
|
||||
// https://developers.google.com/protocol-buffers/docs/proto3#json
|
||||
DecodePolicyHookFunc(),
|
||||
// parse base-64 encoded POLICY that is bound to environment variable
|
||||
DecodePolicyBase64Hook(),
|
||||
decodeJWTClaimHeadersHookFunc(),
|
||||
))
|
||||
)
|
||||
// ViperPolicyHooks are used to decode options and policy coming from YAML and env vars
|
||||
var ViperPolicyHooks = viper.DecodeHook(mapstructure.ComposeDecodeHookFunc(
|
||||
mapstructure.StringToTimeDurationHookFunc(),
|
||||
mapstructure.StringToSliceHookFunc(","),
|
||||
// decode policy including all protobuf-native notations - i.e. duration as `1s`
|
||||
// https://developers.google.com/protocol-buffers/docs/proto3#json
|
||||
DecodePolicyHookFunc(),
|
||||
// parse base-64 encoded POLICY that is bound to environment variable
|
||||
DecodePolicyBase64Hook(),
|
||||
decodeJWTClaimHeadersHookFunc(),
|
||||
decodeCodecTypeHookFunc(),
|
||||
))
|
||||
|
|
|
@ -453,7 +453,7 @@ func (b *Builder) buildMainHTTPConnectionManagerFilter(
|
|||
return nil, err
|
||||
}
|
||||
tc := marshalAny(&envoy_http_connection_manager.HttpConnectionManager{
|
||||
CodecType: envoy_http_connection_manager.HttpConnectionManager_AUTO,
|
||||
CodecType: options.GetCodecType().ToEnvoy(),
|
||||
StatPrefix: "ingress",
|
||||
RouteSpecifier: &envoy_http_connection_manager.HttpConnectionManager_RouteConfig{
|
||||
RouteConfig: rc,
|
||||
|
|
|
@ -290,6 +290,9 @@ type Options struct {
|
|||
// 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
|
||||
|
||||
// CodecType is the codec to use for downstream connections.
|
||||
CodecType CodecType `mapstructure:"codec_type" yaml:"codec_type"`
|
||||
|
||||
AuditKey *PublicKeyEncryptionKeyOptions `mapstructure:"audit_key"`
|
||||
}
|
||||
|
||||
|
@ -940,6 +943,14 @@ func (o *Options) GetQPS() float64 {
|
|||
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
|
||||
func (o *Options) Checksum() uint64 {
|
||||
return hashutil.MustHash(o)
|
||||
|
@ -1177,6 +1188,9 @@ func (o *Options) ApplySettings(settings *config.Settings) {
|
|||
Data: base64.StdEncoding.EncodeToString(settings.AuditKey.GetData()),
|
||||
}
|
||||
}
|
||||
if settings.CodecType != nil {
|
||||
o.CodecType = CodecTypeFromEnvoy(settings.GetCodecType())
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
|
||||
### 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
|
||||
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.
|
||||
shortdoc: |
|
||||
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"
|
||||
doc: |
|
||||
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/timestamp.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";
|
||||
|
||||
|
@ -183,6 +184,8 @@ message Settings {
|
|||
optional uint32 xff_num_trusted_hops = 70;
|
||||
repeated string programmatic_redirect_domain_whitelist = 68;
|
||||
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.
|
||||
|
|
|
@ -8,6 +8,7 @@ function join_by() {
|
|||
|
||||
_protos=(
|
||||
"envoy/annotations/deprecation.proto"
|
||||
"envoy/config/accesslog/v3/accesslog.proto"
|
||||
"envoy/config/cluster/v3/circuit_breaker.proto"
|
||||
"envoy/config/cluster/v3/cluster.proto"
|
||||
"envoy/config/cluster/v3/filter.proto"
|
||||
|
@ -24,17 +25,26 @@ _protos=(
|
|||
"envoy/config/core/v3/protocol.proto"
|
||||
"envoy/config/core/v3/proxy_protocol.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.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/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/string.proto"
|
||||
"envoy/type/matcher/v3/value.proto"
|
||||
"envoy/type/metadata/v3/metadata.proto"
|
||||
"envoy/type/tracing/v3/custom_tag.proto"
|
||||
"envoy/type/v3/http.proto"
|
||||
"envoy/type/v3/http_status.proto"
|
||||
"envoy/type/v3/http.proto"
|
||||
"envoy/type/v3/percent.proto"
|
||||
"envoy/type/v3/range.proto"
|
||||
"envoy/type/v3/semantic_version.proto"
|
||||
|
|
Loading…
Add table
Reference in a new issue