Skip to content

Commit

Permalink
OSSM-5833: Unify curl call from sleep pod (#661)
Browse files Browse the repository at this point in the history
  • Loading branch information
unsortedhashsets authored Feb 12, 2024
1 parent f432d1a commit eb96d5a
Show file tree
Hide file tree
Showing 21 changed files with 225 additions and 366 deletions.
78 changes: 78 additions & 0 deletions pkg/app/sleep.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
package app

import (
"fmt"

"github.com/maistra/maistra-test-tool/pkg/util/check/assert"
"github.com/maistra/maistra-test-tool/pkg/util/check/common"
"github.com/maistra/maistra-test-tool/pkg/util/oc"
"github.com/maistra/maistra-test-tool/pkg/util/pod"
"github.com/maistra/maistra-test-tool/pkg/util/retry"
"github.com/maistra/maistra-test-tool/pkg/util/test"
)

Expand Down Expand Up @@ -53,6 +59,78 @@ func (a *sleep) WaitReady(t test.TestHelper) {
oc.WaitDeploymentRolloutComplete(t, a.ns, "sleep")
}

type CurlOpts struct {
Method string
Headers []string
Options []string
}

func ExecInSleepPod(t test.TestHelper, ns string, command string, checks ...common.CheckFunc) {
t.T().Helper()
retry.UntilSuccess(t, func(t test.TestHelper) {
t.T().Helper()
oc.Exec(t, pod.MatchingSelector("app=sleep", ns), "sleep", command, checks...)
})
}

func AssertSleepPodRequestSuccess(t test.TestHelper, sleepNamespace string, url string, opts ...CurlOpts) {
assertSleepPodRequestResponse(t, sleepNamespace, url, "200", opts...)
}

func AssertSleepPodRequestFailure(t test.TestHelper, sleepNamespace string, url string, opts ...CurlOpts) {
assertSleepPodRequestResponse(t, sleepNamespace, url, curlFailedMessage, opts...)
}

func AssertSleepPodRequestForbidden(t test.TestHelper, sleepNamespace string, url string, opts ...CurlOpts) {
assertSleepPodRequestResponse(t, sleepNamespace, url, "403", opts...)
}

func AssertSleepPodRequestUnauthorized(t test.TestHelper, sleepNamespace string, url string, opts ...CurlOpts) {
assertSleepPodRequestResponse(t, sleepNamespace, url, "401", opts...)
}

func AssertSleepPodZeroesPlaceholder(t test.TestHelper, sleepNamespace string, url string, opts ...CurlOpts) {
assertSleepPodRequestResponse(t, sleepNamespace, url, "000", opts...)
}

func assertSleepPodRequestResponse(t test.TestHelper, sleepNamespace, url, expected string, opts ...CurlOpts) {
command := buildCurlCmd(url, opts...)
ExecInSleepPod(t, sleepNamespace, command,
assert.OutputContains(expected,
fmt.Sprintf("Got expected \"%s\"", expected),
fmt.Sprintf("Expect \"%s\", but got a different response", expected)))
}

func buildCurlCmd(url string, opts ...CurlOpts) string {
var opt CurlOpts
if len(opts) > 0 {
opt = opts[0]
} else {
opt = CurlOpts{}
}

method, headers, options := "", "", ""
if opt.Method == "" {
method = "GET"
} else {
method = opt.Method
}
if opt.Options != nil {
for _, option := range opt.Options {
options += " " + option
}
}
if opt.Headers != nil {
for _, header := range opt.Headers {
headers += fmt.Sprintf(` -H "%s"`, header)
}
}

return fmt.Sprintf(`curl -sS %s%s -X %s -o /dev/null -w "%%{http_code}" %s 2>/dev/null || echo %s`, options, headers, method, url, curlFailedMessage)
}

const curlFailedMessage = "CURL_FAILED"

const sleepTemplate = `
apiVersion: v1
kind: ServiceAccount
Expand Down
30 changes: 12 additions & 18 deletions pkg/tests/ossm/operator/clusterwide_mode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -375,26 +375,20 @@ spec:
oc.WaitSMCPReady(t, meshNamespace, smcpName)

t.LogStep("Check if mTLS is enabled in foo")
retry.UntilSuccess(t, func(t test.TestHelper) {
oc.Exec(t,
pod.MatchingSelector("app=sleep", "foo"),
"sleep",
"curl http://httpbin.foo:8000/headers -s",
assert.OutputContains("X-Forwarded-Client-Cert",
"mTLS is enabled in namespace foo (X-Forwarded-Client-Cert header is present)",
"mTLS is not enabled in namespace foo (X-Forwarded-Client-Cert header is not present)"))
})
app.ExecInSleepPod(t,
"foo",
"curl http://httpbin.foo:8000/headers -s",
assert.OutputContains("X-Forwarded-Client-Cert",
"mTLS is enabled in namespace foo (X-Forwarded-Client-Cert header is present)",
"mTLS is not enabled in namespace foo (X-Forwarded-Client-Cert header is not present)"))

t.LogStep("Check that mTLS is NOT enabled in legacy")
retry.UntilSuccess(t, func(t test.TestHelper) {
oc.Exec(t,
pod.MatchingSelector("app=sleep", "foo"),
"sleep",
"curl http://httpbin.legacy:8000/headers -s",
assert.OutputDoesNotContain("X-Forwarded-Client-Cert",
"mTLS is not enabled in namespace legacy (X-Forwarded-Client-Cert header is not present)",
"mTLS is enabled in namespace legacy, but shouldn't be (X-Forwarded-Client-Cert header is present when it shouldn't be)"))
})
app.ExecInSleepPod(t,
"foo",
"curl http://httpbin.legacy:8000/headers -s",
assert.OutputDoesNotContain("X-Forwarded-Client-Cert",
"mTLS is not enabled in namespace legacy (X-Forwarded-Client-Cert header is not present)",
"mTLS is enabled in namespace legacy, but shouldn't be (X-Forwarded-Client-Cert header is present when it shouldn't be)"))
})

t.NewSubTest("cluster wide works with profiles").Run(func(t test.TestHelper) {
Expand Down
31 changes: 13 additions & 18 deletions pkg/tests/ossm/smoke_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import (
"github.com/maistra/maistra-test-tool/pkg/util/check/assert"
"github.com/maistra/maistra-test-tool/pkg/util/env"
"github.com/maistra/maistra-test-tool/pkg/util/oc"
"github.com/maistra/maistra-test-tool/pkg/util/pod"
"github.com/maistra/maistra-test-tool/pkg/util/retry"
"github.com/maistra/maistra-test-tool/pkg/util/test"
. "github.com/maistra/maistra-test-tool/pkg/util/test"
Expand Down Expand Up @@ -135,23 +134,19 @@ func checkSMCP(t TestHelper, ns string) {
}

func assertTrafficFlowsThroughProxy(t TestHelper, ns string) {
retry.UntilSuccess(t, func(t test.TestHelper) {
oc.Exec(t,
pod.MatchingSelector("app=sleep", ns), "sleep",
"curl -sI http://productpage:9080",
assert.OutputContains(
"HTTP/1.1 200 OK",
"ProductPage returns 200 OK",
"ProductPage didn't return 200 OK"),
assert.OutputContains(
"server: istio-envoy",
"HTTP header 'server: istio-envoy' is present in the response",
"HTTP header 'server: istio-envoy' is missing from the response"),
assert.OutputContains(
"x-envoy-decorator-operation",
"HTTP header 'x-envoy-decorator-operation' is present in the response",
"HTTP header 'x-envoy-decorator-operation' is missing from the response"))
})
app.ExecInSleepPod(t, ns, "curl -sI http://productpage:9080",
assert.OutputContains(
"HTTP/1.1 200 OK",
"ProductPage returns 200 OK",
"ProductPage didn't return 200 OK"),
assert.OutputContains(
"server: istio-envoy",
"HTTP header 'server: istio-envoy' is present in the response",
"HTTP header 'server: istio-envoy' is missing from the response"),
assert.OutputContains(
"x-envoy-decorator-operation",
"HTTP header 'x-envoy-decorator-operation' is present in the response",
"HTTP header 'x-envoy-decorator-operation' is missing from the response"))
}

func assertProxiesReadyInLessThan10Seconds(t TestHelper, ns string) {
Expand Down
35 changes: 17 additions & 18 deletions pkg/tests/tasks/extensions/threescale_wasm_plugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,12 @@ import (
"strings"

"github.com/maistra/maistra-test-tool/pkg/app"
"github.com/maistra/maistra-test-tool/pkg/util/check/assert"
"github.com/maistra/maistra-test-tool/pkg/util/check/require"
"github.com/maistra/maistra-test-tool/pkg/util/curl"
"github.com/maistra/maistra-test-tool/pkg/util/env"
"github.com/maistra/maistra-test-tool/pkg/util/istio"
"github.com/maistra/maistra-test-tool/pkg/util/ns"
"github.com/maistra/maistra-test-tool/pkg/util/oc"
"github.com/maistra/maistra-test-tool/pkg/util/pod"
"github.com/maistra/maistra-test-tool/pkg/util/request"
"github.com/maistra/maistra-test-tool/pkg/util/retry"
"github.com/maistra/maistra-test-tool/pkg/util/test"
Expand Down Expand Up @@ -89,9 +87,11 @@ func TestThreeScaleWasmPlugin(t *testing.T) {

t.LogStep("Deploy sleep app")
app.InstallAndWaitReady(t, app.Sleep(ns.Foo))
httpbinUrl := "http://httpbin:8000/headers"
CurlOpts := app.CurlOpts{Headers: []string{"Authorization: Bearer " + token}}

t.LogStep("Verify that a request from sleep to httpbin with token returns 200")
sendRequestFromSleepToHttpbin(t, token, "200")
app.AssertSleepPodRequestSuccess(t, ns.Foo, httpbinUrl, CurlOpts)

t.LogStep("Apply JWT config and 3scale plugin to sleep")
oc.ApplyTemplate(t, ns.Foo, jwtAuthnTmpl, map[string]interface{}{"AppLabel": "sleep"})
Expand All @@ -102,10 +102,10 @@ func TestThreeScaleWasmPlugin(t *testing.T) {
// JWT authentication filter is applied only to inbound listeners, so 3scale plugin configured
// to use JWT filter metadata always fails on outbound.
t.LogStep("Verify that a request from sleep to httpbin returns 403")
sendRequestFromSleepToHttpbin(t, token, "403")
app.AssertSleepPodRequestForbidden(t, ns.Foo, httpbinUrl, CurlOpts)
} else {
t.LogStep("Verify that a request from sleep to httpbin returns 200")
sendRequestFromSleepToHttpbin(t, token, "200")
app.AssertSleepPodRequestSuccess(t, ns.Foo, httpbinUrl, CurlOpts)
}

if env.GetSMCPVersion().GreaterThanOrEqual(version.SMCP_2_3) {
Expand All @@ -119,9 +119,12 @@ func TestThreeScaleWasmPlugin(t *testing.T) {
oc.WaitSMCPReady(t, meshNamespace, smcpName)
// SMCP v2.5 no longer supports APPLY_WASM_PLUGINS_TO_INBOUND_ONLY
if env.GetSMCPVersion().GreaterThanOrEqual(version.SMCP_2_5) {
sendRequestFromSleepToHttpbin(t, token, "403")
t.LogStep("Verify that a request from sleep to httpbin returns 403, for SMCP v2.5+")
app.AssertSleepPodRequestForbidden(t, ns.Foo, httpbinUrl, CurlOpts)

} else {
sendRequestFromSleepToHttpbin(t, token, "200")
t.LogStep("Verify that a request from sleep to httpbin returns 200")
app.AssertSleepPodRequestSuccess(t, ns.Foo, httpbinUrl, CurlOpts)
}
}

Expand All @@ -134,24 +137,20 @@ func TestThreeScaleWasmPlugin(t *testing.T) {
"ApplyWasmPluginsToInboundOnly": false,
})
oc.WaitSMCPReady(t, meshNamespace, smcpName)
sendRequestFromSleepToHttpbin(t, token, "403")

t.LogStep("Verify that a request from sleep to httpbin returns 403")
app.AssertSleepPodRequestForbidden(t, ns.Foo, httpbinUrl, CurlOpts)

t.LogStep("Enable SERVER mode in the WASM plugin and check if returns 200")
oc.ApplyTemplate(t, ns.Foo, wasmPluginTmpl, map[string]interface{}{
"AppLabel": "sleep",
"ServerMode": true,
})
sendRequestFromSleepToHttpbin(t, token, "200")

t.LogStep("Verify that a request from sleep to httpbin returns 200")
app.AssertSleepPodRequestSuccess(t, ns.Foo, httpbinUrl, CurlOpts)
}
})
}

func sendRequestFromSleepToHttpbin(t test.TestHelper, token, expectedHTTPStatus string) {
retry.UntilSuccess(t, func(t test.TestHelper) {
oc.Exec(t, pod.MatchingSelector("app=sleep", ns.Foo), "sleep",
fmt.Sprintf(`curl http://httpbin:8000/headers -H "Authorization: Bearer %s" -s -o /dev/null -w "%%{http_code}"`, token),
assert.OutputContains(expectedHTTPStatus,
fmt.Sprintf("Received %s as expected", expectedHTTPStatus),
"Received unexpected status code"))
})
}
//fmt.Sprintf(`curl http://httpbin:8000/headers -H "Authorization: Bearer %s" -s -o /dev/null -w "%%{http_code}"`, token),
54 changes: 16 additions & 38 deletions pkg/tests/tasks/security/authentication/auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import (
"github.com/maistra/maistra-test-tool/pkg/util/env"
"github.com/maistra/maistra-test-tool/pkg/util/istio"
"github.com/maistra/maistra-test-tool/pkg/util/oc"
"github.com/maistra/maistra-test-tool/pkg/util/pod"
"github.com/maistra/maistra-test-tool/pkg/util/request"
"github.com/maistra/maistra-test-tool/pkg/util/retry"
. "github.com/maistra/maistra-test-tool/pkg/util/test"
Expand Down Expand Up @@ -63,33 +62,23 @@ func TestAuthPolicy(t *testing.T) {
retry.UntilSuccess(t, func(t TestHelper) {
for _, from := range fromNamespaces {
for _, to := range toNamespaces {
assertConnectionSuccessful(t, from, to)
app.AssertSleepPodRequestSuccess(t, from, fmt.Sprintf("http://httpbin.%s:8000/ip", to))
}
}
})

t.NewSubTest("enable auto mTLS").Run(func(t TestHelper) {
t.LogStep("Check if mTLS is enabled in foo")
retry.UntilSuccess(t, func(t TestHelper) {
oc.Exec(t,
pod.MatchingSelector("app=sleep", "foo"),
"sleep",
"curl http://httpbin.foo:8000/headers -s",
assert.OutputContains("X-Forwarded-Client-Cert",
"mTLS is enabled in namespace foo (X-Forwarded-Client-Cert header is present)",
"mTLS is not enabled in namespace foo (X-Forwarded-Client-Cert header is not present)"))
})
app.ExecInSleepPod(t, "foo", "curl http://httpbin.foo:8000/headers -s",
assert.OutputContains("X-Forwarded-Client-Cert",
"mTLS is enabled in namespace foo (X-Forwarded-Client-Cert header is present)",
"mTLS is not enabled in namespace foo (X-Forwarded-Client-Cert header is not present)"))

t.LogStep("Check that mTLS is NOT enabled in legacy")
retry.UntilSuccess(t, func(t TestHelper) {
oc.Exec(t,
pod.MatchingSelector("app=sleep", "foo"),
"sleep",
"curl http://httpbin.legacy:8000/headers -s",
assert.OutputDoesNotContain("X-Forwarded-Client-Cert",
"mTLS is not enabled in namespace legacy (X-Forwarded-Client-Cert header is not present)",
"mTLS is enabled in namespace legacy, but shouldn't be (X-Forwarded-Client-Cert header is present when it shouldn't be)"))
})
app.ExecInSleepPod(t, "legacy", "curl http://httpbin.legacy:8000/headers -s",
assert.OutputDoesNotContain("X-Forwarded-Client-Cert",
"mTLS is not enabled in namespace legacy (X-Forwarded-Client-Cert header is not present)",
"mTLS is enabled in namespace legacy, but shouldn't be (X-Forwarded-Client-Cert header is present when it shouldn't be)"))
})

t.NewSubTest("enable global mTLS STRICT mode").Run(func(t TestHelper) {
Expand All @@ -98,19 +87,11 @@ func TestAuthPolicy(t *testing.T) {
t.Cleanup(func() {
oc.DeleteFromString(t, meshNamespace, PeerAuthenticationMTLSStrict)
})

t.LogStep("Check whether requests from legacy namespace to foo and bar namespace return 000 placeholder")
retry.UntilSuccess(t, func(t TestHelper) {
from := "legacy"
for _, to := range []string{"foo", "bar"} {
oc.Exec(t,
pod.MatchingSelector("app=sleep", from),
"sleep",
fmt.Sprintf(`curl http://httpbin.%s:8000/ip -s -o /dev/null -w "sleep.%s to httpbin.%s: %%{http_code}" || echo %s`,
to, from, to, curlFailedMessage),
assert.OutputContains("000",
fmt.Sprintf("sleep.%s request to httpbin.%s received expected placeholder 000", from, to),
fmt.Sprintf("sleep.%s request to httpbin.%s, expexted placeholder 000 not found", from, to)))
app.AssertSleepPodZeroesPlaceholder(t, from, fmt.Sprintf("http://httpbin.%s:8000/ip", to))
}
})
})
Expand All @@ -126,10 +107,11 @@ func TestAuthPolicy(t *testing.T) {
retry.UntilSuccess(t, func(t TestHelper) {
for _, from := range []string{"foo", "bar", "legacy"} {
for _, to := range []string{"foo", "bar"} {
url := fmt.Sprintf("http://httpbin.%s:8000/ip", to)
if from == "legacy" && to == "foo" {
assertConnectionFailure(t, from, to)
app.AssertSleepPodRequestFailure(t, from, url)
} else {
assertConnectionSuccessful(t, from, to)
app.AssertSleepPodRequestSuccess(t, from, url)
}
}
}
Expand All @@ -145,15 +127,15 @@ func TestAuthPolicy(t *testing.T) {

t.LogStep("Check whether request failed from legacy namespace to bar namespace")
retry.UntilSuccess(t, func(t TestHelper) {
assertConnectionFailure(t, "legacy", "bar")
app.AssertSleepPodRequestFailure(t, "legacy", "http://httpbin.bar:8000/ip")
})

t.LogStep("Refine mutual TLS per port")
oc.ApplyString(t, "bar", PortPolicy)

t.LogStep("Check whether request succeed from legacy namespace to bar namespace")
retry.UntilSuccess(t, func(t TestHelper) {
assertConnectionSuccessful(t, "legacy", "bar")
app.AssertSleepPodRequestSuccess(t, "legacy", "http://httpbin.bar:8000/ip")
})
})

Expand All @@ -166,7 +148,7 @@ func TestAuthPolicy(t *testing.T) {

t.LogStep("Check whether request succeed legacy namespace to foo namespace")
retry.UntilSuccess(t, func(t TestHelper) {
assertConnectionSuccessful(t, "legacy", "foo")
app.AssertSleepPodRequestSuccess(t, "legacy", "http://httpbin.foo:8000/ip")
})
})

Expand Down Expand Up @@ -243,10 +225,6 @@ func requireResponseStatus(t TestHelper, url string, requestOption curl.RequestO
curl.Request(t, url, requestOption, require.ResponseStatus(statusCode))
}

const (
curlFailedMessage = "CURL_FAILED"
)

const (
WorkloadPolicyStrict = `
apiVersion: security.istio.io/v1beta1
Expand Down
Loading

0 comments on commit eb96d5a

Please sign in to comment.