Harden operator-set target headers (closes #233) (#242)
All checks were successful
check / check (push) Successful in 2m58s
All checks were successful
check / check (push) Successful in 2m58s
This commit was merged in pull request #242.
This commit is contained in:
@@ -26,12 +26,12 @@ func newSSRFTestEngine() *delivery.Engine {
|
||||
return delivery.NewTestEngine(log, client, 1)
|
||||
}
|
||||
|
||||
// TestClientForConfig_TimeoutKeepsSSRFGuard asserts that a
|
||||
// client returned by clientForConfig for a config with a
|
||||
// TestClientForRequest_TimeoutKeepsSSRFGuard asserts that a
|
||||
// client returned by clientForRequest for a config with a
|
||||
// per-target timeout still refuses connections to
|
||||
// private/reserved addresses (the timeout must not drop the
|
||||
// SSRF-safe transport).
|
||||
func TestClientForConfig_TimeoutKeepsSSRFGuard(t *testing.T) {
|
||||
func TestClientForRequest_TimeoutKeepsSSRFGuard(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
engine := newSSRFTestEngine()
|
||||
@@ -51,7 +51,7 @@ func TestClientForConfig_TimeoutKeepsSSRFGuard(t *testing.T) {
|
||||
Timeout: 5,
|
||||
}
|
||||
|
||||
client := engine.ExportClientForConfig(cfg)
|
||||
client := engine.ExportClientForRequest(cfg, nil)
|
||||
|
||||
require.NotSame(t, engine.ExportClient(), client,
|
||||
"a per-target timeout must yield a "+
|
||||
@@ -92,10 +92,11 @@ func TestClientForConfig_TimeoutKeepsSSRFGuard(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestClientForConfig_NoTimeoutUnchanged asserts that with
|
||||
// no per-target timeout the shared SSRF-safe client is
|
||||
// returned unchanged.
|
||||
func TestClientForConfig_NoTimeoutUnchanged(t *testing.T) {
|
||||
// TestClientForRequest_NoTimeoutUnchanged asserts that a
|
||||
// request with neither a per-target timeout nor an origin-scoped
|
||||
// header gets the shared SSRF-safe client unchanged: there is then
|
||||
// nothing for a redirect policy to strip.
|
||||
func TestClientForRequest_NoTimeoutUnchanged(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
engine := newSSRFTestEngine()
|
||||
@@ -104,10 +105,46 @@ func TestClientForConfig_NoTimeoutUnchanged(t *testing.T) {
|
||||
URL: "https://example.com/hook",
|
||||
}
|
||||
|
||||
client := engine.ExportClientForConfig(cfg)
|
||||
client := engine.ExportClientForRequest(cfg, nil)
|
||||
|
||||
assert.Same(t, engine.ExportClient(), client,
|
||||
"without a per-target timeout the shared client "+
|
||||
"must be returned unchanged",
|
||||
)
|
||||
}
|
||||
|
||||
// TestClientForRequest_HeadersKeepSSRFGuard asserts that the
|
||||
// redirect policy an origin-scoped header installs is added to a
|
||||
// client that still carries the SSRF-safe transport. The guard is
|
||||
// a dial hook, so keeping it is what makes each redirect hop pass
|
||||
// the private-IP check too.
|
||||
func TestClientForRequest_HeadersKeepSSRFGuard(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
engine := newSSRFTestEngine()
|
||||
|
||||
cfg := &delivery.HTTPTargetConfig{
|
||||
URL: "https://example.com/with-headers",
|
||||
Headers: map[string]string{
|
||||
"X-Api-Key": "configured",
|
||||
},
|
||||
}
|
||||
|
||||
client := engine.ExportClientForRequest(
|
||||
cfg, []string{"X-Api-Key"},
|
||||
)
|
||||
|
||||
require.NotNil(t, client.CheckRedirect,
|
||||
"an origin-scoped header must install a redirect policy",
|
||||
)
|
||||
|
||||
assert.Same(t,
|
||||
engine.ExportClient().Transport, client.Transport,
|
||||
"the SSRF-safe transport must be reused, not dropped",
|
||||
)
|
||||
|
||||
assert.Equal(t,
|
||||
engine.ExportClient().Timeout, client.Timeout,
|
||||
"the shared client's timeout must be inherited",
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user