mirror of https://github.com/linkerd/linkerd2.git
Test for validating proxy can't be used as an open relay (#7884)
* Test for validating proxy can't be used as open relay Closes #7697 We setup two injected bb servers and an uninjected curl client. One of the servers is injected in ingress mode. The curl client tries to connect to it to the port 4140 while setting the `l5d-dst-override` header to attempt a relay to the other server. The first test shows this doesn't result in a relay. The second test does the same, but changing LINKERD2_PROXY_OUTBOUND_LISTEN_ADDR in the injected server proxy, making it listen on all addresses. In that case, the relay succeeds.
This commit is contained in:
parent
e02ecb4ae6
commit
6d916dd80f
|
|
@ -0,0 +1,148 @@
|
|||
package norelay
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/linkerd/linkerd2/testutil"
|
||||
)
|
||||
|
||||
var TestHelper *testutil.TestHelper
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
TestHelper = testutil.NewTestHelper()
|
||||
// Block test execution until control plane is running
|
||||
TestHelper.WaitUntilDeployReady(testutil.LinkerdDeployReplicasEdge)
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
// TestNoRelay verifies that hitting the proxy's outbound port doesn't result
|
||||
// in an open relay, by trying to leverage the l5d-dst-override header in an
|
||||
// ingress proxy.
|
||||
func TestNoRelay(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
deployments := getDeployments(t)
|
||||
TestHelper.WithDataPlaneNamespace(ctx, "norelay-test", map[string]string{}, t, func(t *testing.T, ns string) {
|
||||
for name, res := range deployments {
|
||||
out, err := TestHelper.KubectlApply(res, ns)
|
||||
if err != nil {
|
||||
testutil.AnnotatedFatalf(t, "unexpected error",
|
||||
"unexpected error with deployment %s: %v output:\n%s",
|
||||
name, err, out,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
for name := range deployments {
|
||||
err := TestHelper.CheckPods(ctx, ns, name, 1)
|
||||
if err != nil {
|
||||
//nolint:errorlint
|
||||
if rce, ok := err.(*testutil.RestartCountError); ok {
|
||||
testutil.AnnotatedWarn(t, "CheckPods timed-out", rce)
|
||||
} else {
|
||||
testutil.AnnotatedError(t, "CheckPods timed-out", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ip, err := TestHelper.Kubectl(
|
||||
"", "-n", ns, "get", "po", "-l", "app=server-relay",
|
||||
"-o", "jsonpath='{range .items[*]}{@.status.podIP}{end}'",
|
||||
)
|
||||
if err != nil {
|
||||
testutil.AnnotatedFatalf(t, "failed to retrieve server-relay IP",
|
||||
"failed to retrieve server-relay IP: %s\n%s", err, ip)
|
||||
}
|
||||
relayIP := strings.Trim(ip, "'")
|
||||
o, err := TestHelper.Kubectl(
|
||||
"", "-n", ns, "exec", "deploy/client",
|
||||
"--", "curl", "-f", "-H", "l5d-dst-override: server-hello."+ns+".svc.cluster.local:8080", "http://"+relayIP+":4140",
|
||||
)
|
||||
if err == nil || err.Error() != "exit status 22" {
|
||||
testutil.AnnotatedFatalf(t, "no error or unexpected error returned",
|
||||
"no error or unexpected error returned: %s\n%s", o, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// TestRelay validates the previous test by running the same scenario but
|
||||
// forcing an open relay by changing the value of
|
||||
// LINKERD2_PROXY_OUTBOUND_LISTEN_ADDR from 127.0.0.1:4140 to 0.0.0.0:4140,
|
||||
// which is not possible without manually changing the injected proxy yaml
|
||||
func TestRelay(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
deployments := getDeployments(t)
|
||||
deployments["server-relay"] = strings.ReplaceAll(deployments["server-relay"], "127.0.0.1:4140", "0.0.0.0:4140")
|
||||
TestHelper.WithDataPlaneNamespace(ctx, "relay-test", map[string]string{}, t, func(t *testing.T, ns string) {
|
||||
for name, res := range deployments {
|
||||
out, err := TestHelper.KubectlApply(res, ns)
|
||||
if err != nil {
|
||||
testutil.AnnotatedFatalf(t, "unexpected error",
|
||||
"unexpected error with deployment %s: %v output:\n%s",
|
||||
name, err, out,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
for name := range deployments {
|
||||
err := TestHelper.CheckPods(ctx, ns, name, 1)
|
||||
if err != nil {
|
||||
//nolint:errorlint
|
||||
if rce, ok := err.(*testutil.RestartCountError); ok {
|
||||
testutil.AnnotatedWarn(t, "CheckPods timed-out", rce)
|
||||
} else {
|
||||
testutil.AnnotatedError(t, "CheckPods timed-out", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ip, err := TestHelper.Kubectl(
|
||||
"", "-n", ns, "get", "po", "-l", "app=server-relay",
|
||||
"-o", "jsonpath='{range .items[*]}{@.status.podIP}{end}'",
|
||||
)
|
||||
if err != nil {
|
||||
testutil.AnnotatedFatalf(t, "failed to retrieve server-relay IP",
|
||||
"failed to retrieve server-relay IP: %s\n%s", err, ip)
|
||||
}
|
||||
relayIP := strings.Trim(ip, "'")
|
||||
o, err := TestHelper.Kubectl(
|
||||
"", "-n", ns, "exec", "deploy/client",
|
||||
"--", "curl", "-f", "-H", "l5d-dst-override: server-hello."+ns+".svc.cluster.local:8080", "http://"+relayIP+":4140",
|
||||
)
|
||||
if err != nil {
|
||||
testutil.AnnotatedFatalf(t, "unexpected error returned",
|
||||
"unexpected error returned: %s\n%s", o, err)
|
||||
}
|
||||
if !strings.Contains(o, "HELLO-FROM-SERVER") {
|
||||
testutil.AnnotatedFatalf(t, "unexpected response returned",
|
||||
"unexpected response returned: %s", o)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func getDeployments(t *testing.T) map[string]string {
|
||||
deploys := make(map[string]string)
|
||||
var err error
|
||||
|
||||
// server-hello is injected normally
|
||||
deploys["server-hello"], err = TestHelper.LinkerdRun("inject", "testdata/server-hello.yml")
|
||||
if err != nil {
|
||||
testutil.AnnotatedFatal(t, "unexpected error", err)
|
||||
}
|
||||
|
||||
// server-relay is injected in ingress mode, manually
|
||||
deploys["server-relay"], err = TestHelper.LinkerdRun("inject", "--manual", "--ingress", "testdata/server-relay.yml")
|
||||
if err != nil {
|
||||
testutil.AnnotatedFatal(t, "unexpected error", err)
|
||||
}
|
||||
|
||||
// client is not injected
|
||||
deploys["client"], err = testutil.ReadFile("testdata/client.yml")
|
||||
if err != nil {
|
||||
testutil.AnnotatedFatalf(t, "failed to read 'client.yml'", "failed to read 'client.yml': %s", err)
|
||||
}
|
||||
|
||||
return deploys
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: client
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: client
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: client
|
||||
spec:
|
||||
containers:
|
||||
- name: curl
|
||||
image: curlimages/curl
|
||||
command: [ "sh", "-c", "--" ]
|
||||
args: [ "while true; do sleep 10; done;" ]
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: server-hello
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: server-hello
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: server-hello
|
||||
spec:
|
||||
containers:
|
||||
- name: app
|
||||
image: buoyantio/bb:v0.0.6
|
||||
args:
|
||||
- terminus
|
||||
- "--h1-server-port=8080"
|
||||
- "--response-text=HELLO-FROM-SERVER"
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: server-hello
|
||||
spec:
|
||||
selector:
|
||||
app: server-hello
|
||||
ports:
|
||||
- name: http
|
||||
port: 8080
|
||||
targetPort: 8080
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: server-relay
|
||||
labels:
|
||||
app: server-relay
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: server-relay
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: server-relay
|
||||
spec:
|
||||
containers:
|
||||
- name: app
|
||||
image: buoyantio/bb:v0.0.6
|
||||
args:
|
||||
- terminus
|
||||
- "--h1-server-port=8080"
|
||||
- "--response-text=HELLO-FROM-RELAY"
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: server-relay
|
||||
spec:
|
||||
selector:
|
||||
app: server-relay
|
||||
ports:
|
||||
- name: http
|
||||
port: 8080
|
||||
targetPort: 8080
|
||||
Loading…
Reference in New Issue