Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

envoy: add support for bind_config bootstrap options #2772

Merged
merged 3 commits into from Dec 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions config/constants.go
Expand Up @@ -34,6 +34,7 @@ var ViperPolicyHooks = viper.DecodeHook(mapstructure.ComposeDecodeHookFunc(
DecodePolicyHookFunc(),
// parse base-64 encoded POLICY that is bound to environment variable
DecodePolicyBase64Hook(),
decodeNullBoolHookFunc(),
decodeJWTClaimHeadersHookFunc(),
decodeCodecTypeHookFunc(),
decodePPLPolicyHookFunc(),
Expand Down
23 changes: 21 additions & 2 deletions config/custom.go
Expand Up @@ -13,16 +13,35 @@ import (

envoy_config_cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3"
"github.com/mitchellh/mapstructure"
"github.com/volatiletech/null/v9"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/proto"
"gopkg.in/yaml.v3"

"github.com/pomerium/pomerium/pkg/policy/parser"

"github.com/pomerium/pomerium/internal/httputil"
"github.com/pomerium/pomerium/internal/urlutil"
"github.com/pomerium/pomerium/pkg/policy/parser"
)

func decodeNullBoolHookFunc() mapstructure.DecodeHookFunc {
return func(f, t reflect.Type, data interface{}) (interface{}, error) {
if t != reflect.TypeOf(null.Bool{}) {
return data, nil
}

bs, err := json.Marshal(data)
if err != nil {
return nil, err
}
var value null.Bool
err = json.Unmarshal(bs, &value)
if err != nil {
return nil, err
}
return value, nil
}
}

// JWTClaimHeaders are headers to add to a request based on IDP claims.
type JWTClaimHeaders map[string]string

Expand Down
22 changes: 22 additions & 0 deletions config/envoyconfig/clusters.go
Expand Up @@ -137,6 +137,28 @@ func (b *Builder) buildPolicyCluster(ctx context.Context, options *config.Option
cluster := new(envoy_config_cluster_v3.Cluster)
proto.Merge(cluster, policy.EnvoyOpts)

if options.EnvoyBindConfigFreebind.IsSet() || options.EnvoyBindConfigSourceAddress != "" {
cluster.UpstreamBindConfig = new(envoy_config_core_v3.BindConfig)
if options.EnvoyBindConfigFreebind.IsSet() {
cluster.UpstreamBindConfig.Freebind = wrapperspb.Bool(options.EnvoyBindConfigFreebind.Bool)
}
if options.EnvoyBindConfigSourceAddress != "" {
cluster.UpstreamBindConfig.SourceAddress = &envoy_config_core_v3.SocketAddress{
Address: options.EnvoyBindConfigSourceAddress,
PortSpecifier: &envoy_config_core_v3.SocketAddress_PortValue{
PortValue: 0,
},
}
} else {
cluster.UpstreamBindConfig.SourceAddress = &envoy_config_core_v3.SocketAddress{
Address: "0.0.0.0",
PortSpecifier: &envoy_config_core_v3.SocketAddress_PortValue{
PortValue: 0,
},
}
}
}

cluster.AltStatName = getClusterStatsName(policy)
upstreamProtocol := getUpstreamProtocolForPolicy(ctx, policy)

Expand Down
52 changes: 52 additions & 0 deletions config/envoyconfig/clusters_test.go
Expand Up @@ -6,10 +6,12 @@ import (
"os"
"path/filepath"
"testing"
"time"

envoy_config_cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/volatiletech/null/v9"
"google.golang.org/protobuf/types/known/wrapperspb"

"github.com/pomerium/pomerium/config"
Expand Down Expand Up @@ -828,6 +830,56 @@ func Test_validateClusters(t *testing.T) {
}
}

func Test_bindConfig(t *testing.T) {
ctx, clearTimeout := context.WithTimeout(context.Background(), time.Second*10)
defer clearTimeout()

b := New("local-grpc", "local-http", filemgr.NewManager(), nil)
t.Run("no bind config", func(t *testing.T) {
cluster, err := b.buildPolicyCluster(ctx, &config.Options{}, &config.Policy{
From: "https://from.example.com",
To: mustParseWeightedURLs(t, "https://to.example.com"),
})
assert.NoError(t, err)
assert.Nil(t, cluster.UpstreamBindConfig)
})
t.Run("freebind", func(t *testing.T) {
cluster, err := b.buildPolicyCluster(ctx, &config.Options{
EnvoyBindConfigFreebind: null.BoolFrom(true),
}, &config.Policy{
From: "https://from.example.com",
To: mustParseWeightedURLs(t, "https://to.example.com"),
})
assert.NoError(t, err)
testutil.AssertProtoJSONEqual(t, `
{
"freebind": true,
"sourceAddress": {
"address": "0.0.0.0",
"portValue": 0
}
}
`, cluster.UpstreamBindConfig)
})
t.Run("source address", func(t *testing.T) {
cluster, err := b.buildPolicyCluster(ctx, &config.Options{
EnvoyBindConfigSourceAddress: "192.168.0.1",
}, &config.Policy{
From: "https://from.example.com",
To: mustParseWeightedURLs(t, "https://to.example.com"),
})
assert.NoError(t, err)
testutil.AssertProtoJSONEqual(t, `
{
"sourceAddress": {
"address": "192.168.0.1",
"portValue": 0
}
}
`, cluster.UpstreamBindConfig)
})
}

func mustParseWeightedURLs(t *testing.T, urls ...string) []config.WeightedURL {
wu, err := config.ParseWeightedUrls(urls...)
require.NoError(t, err)
Expand Down
11 changes: 7 additions & 4 deletions config/options.go
Expand Up @@ -18,6 +18,7 @@ import (

"github.com/mitchellh/mapstructure"
"github.com/spf13/viper"
"github.com/volatiletech/null/v9"

"github.com/pomerium/pomerium/internal/directory/azure"
"github.com/pomerium/pomerium/internal/directory/github"
Expand Down Expand Up @@ -279,10 +280,12 @@ type Options struct {
// see https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_man/headers.html?highlight=xff_num_trusted_hops#x-forwarded-for
XffNumTrustedHops uint32 `mapstructure:"xff_num_trusted_hops" yaml:"xff_num_trusted_hops,omitempty" json:"xff_num_trusted_hops,omitempty"`

// Envoy bootstrap admin options. These do not support dynamic updates.
EnvoyAdminAccessLogPath string `mapstructure:"envoy_admin_access_log_path" yaml:"envoy_admin_access_log_path"`
EnvoyAdminProfilePath string `mapstructure:"envoy_admin_profile_path" yaml:"envoy_admin_profile_path"`
EnvoyAdminAddress string `mapstructure:"envoy_admin_address" yaml:"envoy_admin_address"`
// Envoy bootstrap options. These do not support dynamic updates.
EnvoyAdminAccessLogPath string `mapstructure:"envoy_admin_access_log_path" yaml:"envoy_admin_access_log_path"`
EnvoyAdminProfilePath string `mapstructure:"envoy_admin_profile_path" yaml:"envoy_admin_profile_path"`
EnvoyAdminAddress string `mapstructure:"envoy_admin_address" yaml:"envoy_admin_address"`
EnvoyBindConfigSourceAddress string `mapstructure:"envoy_bind_config_source_address" yaml:"envoy_bind_config_source_address,omitempty"`
EnvoyBindConfigFreebind null.Bool `mapstructure:"envoy_bind_config_freebind" yaml:"envoy_bind_config_freebind,omitempty"`

// 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
Expand Down
8 changes: 4 additions & 4 deletions docs/reference/readme.md
Expand Up @@ -674,13 +674,13 @@ tracing_zipkin_endpoint | Url to the Zipkin HTTP endpoint. | ✅
Setting `use_proxy_protocol` will configure Pomerium to require the [HAProxy proxy protocol](https://www.haproxy.org/download/1.9/doc/proxy-protocol.txt) on incoming connections. Versions 1 and 2 of the protocol are supported.


### Envoy Admin Options
- Environment Variable: `ENVOY_ADMIN_ADDRESS`, `ENVOY_ADMIN_ACCESS_LOG_PATH`, `ENVOY_ADMIN_PROFILE_PATH`
- Config File Keys: `envoy_admin_address`, `envoy_admin_access_log_path`, `envoy_admin_profile_path`
### Envoy Bootstrap Options
- Environment Variable: `ENVOY_ADMIN_ADDRESS`, `ENVOY_ADMIN_ACCESS_LOG_PATH`, `ENVOY_ADMIN_PROFILE_PATH`, `ENVOY_BIND_CONFIG_FREEBIND`, `ENVOY_BIND_CONFIG_SOURCE_ADDRESS`
- Config File Keys: `envoy_admin_address`, `envoy_admin_access_log_path`, `envoy_admin_profile_path`, `envoy_bind_config_freebind`, `envoy_bind_config_source_address`
- Type: `string`
- Optional

These options customize Envoy's [bootstrap configuration](https://www.envoyproxy.io/docs/envoy/latest/operations/admin#operations-admin-interface). They cannot be modified at runtime.
The `envoy_admin` keys customize Envoy's [bootstrap configuration](https://www.envoyproxy.io/docs/envoy/latest/operations/admin#operations-admin-interface). The `envoy_bind_config` keys modify the [ClusterManager](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/bootstrap/v3/bootstrap.proto.html#config-bootstrap-v3-clustermanager) configuration. These options cannot be modified at runtime.


## Authenticate Service
Expand Down
10 changes: 5 additions & 5 deletions docs/reference/settings.yaml
Expand Up @@ -764,15 +764,15 @@ settings:
- Optional
doc: |
Setting `use_proxy_protocol` will configure Pomerium to require the [HAProxy proxy protocol](https://www.haproxy.org/download/1.9/doc/proxy-protocol.txt) on incoming connections. Versions 1 and 2 of the protocol are supported.
- name: "Envoy Admin Options"
keys: ["envoy_admin_options"]
- name: "Envoy Bootstrap Options"
keys: ["envoy_admin_address","envoy_admin_access_log_path","envoy_admin_profile_path","envoy_bind_config_freebind","envoy_bind_config_source_address"]
attributes: |
- Environment Variable: `ENVOY_ADMIN_ADDRESS`, `ENVOY_ADMIN_ACCESS_LOG_PATH`, `ENVOY_ADMIN_PROFILE_PATH`
- Config File Keys: `envoy_admin_address`, `envoy_admin_access_log_path`, `envoy_admin_profile_path`
- Environment Variable: `ENVOY_ADMIN_ADDRESS`, `ENVOY_ADMIN_ACCESS_LOG_PATH`, `ENVOY_ADMIN_PROFILE_PATH`, `ENVOY_BIND_CONFIG_FREEBIND`, `ENVOY_BIND_CONFIG_SOURCE_ADDRESS`
- Config File Keys: `envoy_admin_address`, `envoy_admin_access_log_path`, `envoy_admin_profile_path`, `envoy_bind_config_freebind`, `envoy_bind_config_source_address`
- Type: `string`
- Optional
doc: |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The doc section should probably work in a link to the cluster manager proto for these options.

/cc @alexfornuto

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@travisgroth: Updated, should be reviewed by an SME.

These options customize Envoy's [bootstrap configuration](https://www.envoyproxy.io/docs/envoy/latest/operations/admin#operations-admin-interface). They cannot be modified at runtime.
The `envoy_admin` keys customize Envoy's [bootstrap configuration](https://www.envoyproxy.io/docs/envoy/latest/operations/admin#operations-admin-interface). The `envoy_bind_config` keys modify the [ClusterManager](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/bootstrap/v3/bootstrap.proto.html#config-bootstrap-v3-clustermanager) configuration. These options cannot be modified at runtime.
- name: "Authenticate Service"
settings:
- name: "Authenticate Callback Path"
Expand Down
1 change: 1 addition & 0 deletions go.mod
Expand Up @@ -59,6 +59,7 @@ require (
github.com/tniswong/go.rfcx v0.0.0-20181019234604-07783c52761f
github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80
github.com/vektah/gqlparser v1.3.1
github.com/volatiletech/null/v9 v9.0.0
github.com/yuin/gopher-lua v0.0.0-20200816102855-ee81675732da
go.opencensus.io v0.23.0
go.uber.org/zap v1.19.1
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Expand Up @@ -1327,6 +1327,8 @@ github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:tw
github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI=
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
github.com/volatiletech/null/v9 v9.0.0 h1:JCdlHEiSRVxOi7/MABiEfdsqmuj9oTV20Ao7VvZ0JkE=
github.com/volatiletech/null/v9 v9.0.0/go.mod h1:zRFghPVahaiIMRXiUJrc6gsoG83Cm3ZoAfSTw7VHGQc=
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
Expand Down