Replace Atoi() calls with ParseUint(), and update the buildAddress()
defaultPort parameter to be a uint32. (A uint16 would arguably make more
sense for a port number, but uint32 matches the Envoy proto field.)
Delete a ParseAddress() method that appears to be unused.
Add a distinction between TCP routes depending on whether the To URL(s)
have the scheme tcp://. For routes with a TCP upstream, configure Envoy
to terminate CONNECT requests and open a TCP tunnel to the upstream
service (this is the current behavior). For routes without a TCP
upstream, configure Envoy to proxy CONNECT requests to the upstream.
This new mode can allow an upstream proxy server to terminate a CONNECT
request and open its own TCP tunnel to the final destination server.
(Note that this will typically require setting the preserve_host_header
option as well.)
Note that this requires Envoy 1.30 or later.
Envoy has an option 'auto_host_rewrite' that rewrites the Host header of
an incoming request to match the upstream domain that the proxied
request is sent to. Pomerium sets the 'auto_host_rewrite' option for all
Pomerium routes that do not set one of the "Host Rewrite options" (see
https://www.pomerium.com/docs/reference/routes/headers#host-rewrite-options).
When Envoy rewrites the Host header, it does not include the upstream
port, even when it is a non-standard port for the scheme (i.e. a port
other than 80 for http or a port other than 443 for https).
I think this behavior does not conform to RFC 9110. The nearest thing I
can find in the text is this statement about http and https URIs:
"If the port is equal to the default port for a scheme, the normal form
is to omit the port subcomponent."
(from https://datatracker.ietf.org/doc/html/rfc9110#section-4.2.3)
I take this to mean that the port should be specified in other cases.
There is a work-around: we can set an explicit hostname on each cluster
endpoint. Let's set this hostname based on the 'to' URL(s) from the
Pomerium route.
This should change the current behavior in two cases:
- When a route has a 'to' URL with a port number, this port number will
now be included in the Host header in the requests made by Pomerium.
- When a route has a 'to' URL with 'localhost' or an IP address as the
host, Pomerium will now rewrite the Host header to match the 'to'
URL.
There should be no change in behavior for routes where one of the "Host
Rewrite options" is set.
The client_ca and client_ca_file settings were deprecated in v0.23.
Remove these options and add a link to the corresponding explanation on
the Upgrading docs page.
In split service mode, and during periods of inactivity, the gRPC
connections to the databroker may fall idle. Some network firewalls may
eventually time out an idle TCP connection and even start dropping
subsequent packets once connection traffic resumes. Combined with Linux
default TCP retransmission settings, this could cause a broken
connection to persist for over 15 minutes.
In an attempt to avoid this scenario, enable TCP keepalive for outbound
gRPC connections, matching the Go standard library default settings for
time & interval: 15 seconds for both. (The probe count does not appear
to be set, so it will remain at the OS default.)
Add a test case exercising the BuildClusters() method with the default
configuration options, comparing the results with a reference "golden"
file in the testdata directory. Also add an '-update' flag to make it
easier to update the reference golden when needed:
go test ./config/envoyconfig -update
This partially reverts commit a1388592d8.
Fetching the authenticate service HPKE public key is required only for
the stateless authentication flow. Now that Pomerium will instead use
the older (stateful) authentication flow when configured for a
self-hosted authenticate service, this logic shouldn't be needed at all.
Removing this logic should also make it easier to test against a local
instance of the hosted authenticate service.
Add an environment variable to allow forcing either the stateful or the
stateless authenticate flow.
Split the existing integration test clusters "single" and "multi" into
four new clusters: "single-stateful", "single-stateless",
"multi-stateful", and "multi-stateless", so that the integration tests
will run for both the stateful and the stateless authenticate flows.
(The "kubernetes" cluster is not currently being run, so I've left it
alone for now.)
Update the initialization logic for the authenticate, authorize, and
proxy services to automatically select between the stateful
authentication flow and the stateless authentication flow, depending on
whether Pomerium is configured to use the hosted authenticate service.
Add a unit test case to verify that the sign_out handler does not
trigger a sign in redirect.
* core/config: update file watcher source to handle base64 encoded certificates
* fix data race
* core/config: only allow files in certificates
* remove test
* re-add test
* core/config: refactor file watcher
* add comments
* updates
* only use the polling watcher
* fix test
* fix test
* try to fix test again
* remove batching
* dont rely on file modification timestamp
* remove benchmark
* try fix again
Remove the Redis databroker backend. According to
https://www.pomerium.com/docs/internals/data-storage#redis it has been
discouraged since Pomerium v0.18.
Update the config options validation to return an error if "redis" is
set as the databroker storage backend type.
* core/config: refactor change dispatcher
* update test
* close listener go routine when context is canceled
* use cancel cause
* use context
* add more time
* more time
Currently the GetSetResponseHeadersForPolicy() method may add entries to
the global SetResponseHeaders map, which can lead to one route's headers
being applied to other routes.
Instead, make a copy of the SetResponseHeaders map before adding any
route-specific response header entries.
Add additional unit tests for GetSetResponseHeaders() and
GetSetResponseHeadersForPolicy().
Remove the deprecated set_authorization_header option entirely. Add an
entry to the removedConfigFields map with a link to the relevant
Upgrading page section.
Set the Envoy option only_verify_leaf_cert_crl, to avoid a bug where
CRLs cannot be used in combination with an intermediate CA trust root.
Update the client certificate validation logic in the authorize service
to match this behavior.
Fix the logic around when to add the default invalid_client_certificate
rule: this should only be added if mTLS is enabled and the enforcement
mode is not set to "policy". Add a unit test for this logic.
If Pomerium is operating in the insecure_server mode (e.g. if there is
another reverse proxy in front of Pomerium), then the ssl() Lua method
will return nil.
Add a check for this case to the set-client-certificate-metadata.lua
script, in order to avoid an error when attempting to store the client
certificate info.
Currently Pomerium replaces dynamic set_request_headers tokens
sequentially. As a result, if a replacement value itself contained a
supported "$pomerium" token, Pomerium may treat that as another
replacement, resulting in incorrect output.
This is unlikely to be a problem given the current set of dynamic
tokens, but if we continue to add additional tokens, this will likely
become more of a concern.
To forestall any issues, let's perform all replacements in one pass,
using the os.Expand() method. This does require a slight change to the
syntax, as tokens containing a '.' will need to be wrapped in curly
braces, e.g. ${pomerium.id_token}.
A literal dollar sign can be included by using $$ in the input.
Add a new match_subject_alt_names option to the downstream_mtls settings
group. This setting can be used to further constrain the allowed client
certificates by requiring that certificates contain a Subject
Alternative Name of a particular type, matching a particular regex.
When set, populate the corresponding match_typed_subject_alt_names
setting within Envoy, and also implement a corresponding check in the
authorize service.
Move the parseCRLs() method from package 'authorize/evaluator' to
'pkg/cryptutil', replacing the existing DecodeCRL() method. This method
will parse all CRLs found in the PEM input, rather than just the first.
(This removes our usage of the deprecated method x509.ParseDERCRL.)
Update this method to return an error if there is non-PEM data found in
the input, to satisfy the existing test that raw DER-encoded CRLs are
not permitted.
Delete the CRLFromBase64() and CRLFromFile() methods, as these are no
longer used.
Add a new max_verify_depth option to the downstream_mtls settings group,
with a default value of 1 (to match the behavior of current Pomerium
releases).
Populate the corresponding setting within Envoy, and also implement a
depth check within isValidClientCertificate() in the authorize service.