-
Notifications
You must be signed in to change notification settings - Fork 44
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
OSSM-3647: Add tests for 3scale plugin (#633)
* OSSM-3647: Add a test for 3scale plugin applied to an ingress gateway Signed-off-by: Jacek Ewertowski <[email protected]> * Run TestThreeScaleWasmPlugin for all supported versions Signed-off-by: Jacek Ewertowski <[email protected]> * Rename test Signed-off-by: Jacek Ewertowski <[email protected]> * Remove unused file Signed-off-by: Jacek Ewertowski <[email protected]> * Use official wiremock image Signed-off-by: Jacek Ewertowski <[email protected]> * Fix execution order Signed-off-by: Jacek Ewertowski <[email protected]> * Test more cases with 3scale plugin Signed-off-by: Jacek Ewertowski <[email protected]> * Revert changes from auth tests Signed-off-by: Jacek Ewertowski <[email protected]> * Fix lint error Signed-off-by: Jacek Ewertowski <[email protected]> --------- Signed-off-by: Jacek Ewertowski <[email protected]>
- Loading branch information
Showing
9 changed files
with
535 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package extensions | ||
|
||
import ( | ||
_ "embed" | ||
|
||
"github.com/maistra/maistra-test-tool/pkg/tests/ossm" | ||
"github.com/maistra/maistra-test-tool/pkg/util/env" | ||
"github.com/maistra/maistra-test-tool/pkg/util/test" | ||
|
||
"testing" | ||
) | ||
|
||
var ( | ||
smcpName = env.GetDefaultSMCPName() | ||
meshNamespace = env.GetDefaultMeshNamespace() | ||
threeScaleNs = "3scale" | ||
|
||
//go:embed yaml/3scale-system.yaml | ||
threeScaleSystem string | ||
|
||
//go:embed yaml/3scale-system-service-entry.yaml | ||
threeScaleSystemSvcEntry string | ||
|
||
//go:embed yaml/3scale-backend.yaml | ||
threeScaleBackend string | ||
|
||
//go:embed yaml/3scale-backend-service-entry.yaml | ||
threeScaleBackendSvcEntry string | ||
|
||
//go:embed yaml/mesh.tmpl.yaml | ||
meshTmpl string | ||
|
||
//go:embed yaml/jwt-authn.tmpl.yaml | ||
jwtAuthnTmpl string | ||
|
||
//go:embed yaml/wasm-plugin.tmpl.yaml | ||
wasmPluginTmpl string | ||
) | ||
|
||
func TestMain(m *testing.M) { | ||
test.NewSuite(m). | ||
Setup(ossm.BasicSetup). | ||
Run() | ||
} |
120 changes: 120 additions & 0 deletions
120
pkg/tests/tasks/extensions/threescale_wasm_plugin_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
package extensions | ||
|
||
import ( | ||
"fmt" | ||
"net/http" | ||
"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" | ||
"github.com/maistra/maistra-test-tool/pkg/util/version" | ||
|
||
"testing" | ||
) | ||
|
||
const ( | ||
tokenURL = "https://raw.githubusercontent.com/istio/istio/release-1.19/security/tools/jwt/samples/demo.jwt" | ||
) | ||
|
||
func TestThreeScaleWasmPlugin(t *testing.T) { | ||
test.NewTest(t).Groups(test.Full).Run(func(t test.TestHelper) { | ||
t.Cleanup(func() { | ||
oc.RecreateNamespace(t, ns.Foo) | ||
oc.RecreateNamespace(t, meshNamespace) | ||
oc.DeleteNamespace(t, threeScaleNs) | ||
}) | ||
|
||
meshValues := map[string]string{ | ||
"Name": smcpName, | ||
"Version": env.GetSMCPVersion().String(), | ||
"Member": ns.Foo, | ||
} | ||
|
||
t.LogStep("Deploy SMCP") | ||
oc.ApplyTemplate(t, meshNamespace, meshTmpl, meshValues) | ||
oc.WaitSMCPReady(t, meshNamespace, smcpName) | ||
|
||
t.LogStep("Deploy 3scale mocks") | ||
oc.CreateNamespace(t, threeScaleNs) | ||
oc.ApplyString(t, threeScaleNs, threeScaleBackend) | ||
oc.ApplyString(t, meshNamespace, threeScaleBackendSvcEntry) | ||
oc.ApplyString(t, threeScaleNs, threeScaleSystem) | ||
oc.ApplyString(t, meshNamespace, threeScaleSystemSvcEntry) | ||
oc.WaitAllPodsReady(t, threeScaleNs) | ||
|
||
t.LogStep("Configure JWT authn") | ||
oc.ApplyTemplate(t, meshNamespace, jwtAuthnTmpl, map[string]interface{}{ | ||
"AppLabel": "istio-ingressgateway", | ||
"ForwardToken": true, | ||
}) | ||
|
||
t.LogStep("Apply 3scale WASM plugin to the ingress gateway") | ||
oc.ApplyTemplate(t, meshNamespace, wasmPluginTmpl, map[string]interface{}{"AppLabel": "istio-ingressgateway"}) | ||
|
||
t.LogStep("Deploy httpbin and configure its gateway and routing") | ||
app.InstallAndWaitReady(t, app.Httpbin(ns.Foo)) | ||
oc.ApplyFile(t, ns.Foo, "https://raw.githubusercontent.com/maistra/istio/maistra-2.4/samples/httpbin/httpbin-gateway.yaml") | ||
|
||
t.LogStep("Verify that a request to the ingress gateway with token returns 200") | ||
ingressGatewayHost := istio.GetIngressGatewayHost(t, meshNamespace) | ||
headersURL := fmt.Sprintf("http://%s/headers", ingressGatewayHost) | ||
token := string(curl.Request(t, tokenURL, nil)) | ||
token = strings.Trim(token, "\n") | ||
retry.UntilSuccess(t, func(t test.TestHelper) { | ||
curl.Request(t, headersURL, request.WithHeader("Authorization", "Bearer "+token), require.ResponseStatus(http.StatusOK)) | ||
}) | ||
|
||
t.LogStep("Apply JWT config and 3scale plugin to httpbin") | ||
oc.ApplyTemplate(t, ns.Foo, jwtAuthnTmpl, map[string]interface{}{"AppLabel": "httpbin"}) | ||
oc.ApplyTemplate(t, ns.Foo, wasmPluginTmpl, map[string]interface{}{"AppLabel": "httpbin"}) | ||
|
||
// This step would fail if the ingress gateway did not forward Authorization header to httpbin | ||
t.LogStep("Verify that a request to the ingress gateway with token returns 200") | ||
retry.UntilSuccess(t, func(t test.TestHelper) { | ||
curl.Request(t, headersURL, request.WithHeader("Authorization", "Bearer "+token), require.ResponseStatus(http.StatusOK)) | ||
}) | ||
|
||
t.LogStep("Deploy sleep app") | ||
app.InstallAndWaitReady(t, app.Sleep(ns.Foo)) | ||
|
||
t.LogStep("Verify that a request from sleep to httpbin with token returns 200") | ||
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("200", "Received 200 as expected", "Received unexpected status code")) | ||
}) | ||
|
||
t.LogStep("Apply JWT config and 3scale plugin to sleep") | ||
oc.ApplyTemplate(t, ns.Foo, jwtAuthnTmpl, map[string]interface{}{"AppLabel": "sleep"}) | ||
oc.ApplyTemplate(t, ns.Foo, wasmPluginTmpl, map[string]interface{}{"AppLabel": "sleep"}) | ||
|
||
if env.GetSMCPVersion().GreaterThanOrEqual(version.SMCP_2_3) { | ||
// A request should fail, because in 2.3 and 2.4, WASM plugins are applied to inbound and outbound listeners. | ||
// 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") | ||
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("403", "Received 403 as expected", "Received unexpected status code")) | ||
}) | ||
} else { | ||
t.LogStep("Verify that a request from sleep to httpbin returns 200") | ||
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("200", "Received 200 as expected", "Received unexpected status code")) | ||
}) | ||
} | ||
}) | ||
} |
13 changes: 13 additions & 0 deletions
13
pkg/tests/tasks/extensions/yaml/3scale-backend-service-entry.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
apiVersion: networking.istio.io/v1beta1 | ||
kind: ServiceEntry | ||
metadata: | ||
name: threescale-backend | ||
spec: | ||
hosts: | ||
- backend.3scale.svc.cluster.local | ||
ports: | ||
- number: 80 | ||
name: http | ||
protocol: HTTP | ||
location: MESH_EXTERNAL | ||
resolution: DNS |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
apiVersion: apps/v1 | ||
kind: Deployment | ||
metadata: | ||
name: backend | ||
namespace: 3scale | ||
labels: | ||
3scale: backend | ||
spec: | ||
selector: | ||
matchLabels: | ||
3scale: backend | ||
template: | ||
metadata: | ||
labels: | ||
3scale: backend | ||
spec: | ||
containers: | ||
- name: wiremock | ||
image: wiremock/wiremock:3.2.0 | ||
imagePullPolicy: IfNotPresent | ||
ports: | ||
- containerPort: 8080 | ||
volumeMounts: | ||
- name: wiremock-mapping | ||
mountPath: /home/wiremock/mappings | ||
volumes: | ||
- name: wiremock-mapping | ||
configMap: | ||
name: wiremock-mapping-3scale-backend | ||
--- | ||
apiVersion: v1 | ||
kind: Service | ||
metadata: | ||
name: backend | ||
namespace: 3scale | ||
labels: | ||
3scale: backend | ||
spec: | ||
type: ClusterIP | ||
selector: | ||
3scale: backend | ||
ports: | ||
- port: 80 | ||
targetPort: 8080 | ||
--- | ||
# This is a mock response for 3scale backend API, which is called on plugin initialization to fetch a configuration for specified services. | ||
apiVersion: v1 | ||
kind: ConfigMap | ||
metadata: | ||
name: wiremock-mapping-3scale-backend | ||
namespace: 3scale | ||
data: | ||
static.json: | | ||
{ | ||
"request": { | ||
"method": "GET", | ||
"url": "/transactions/authrep.xml?service_id=123&service_token=3d3bfe783a66ad7576c2389d4a8623ea613cc5146dce2e603b001ccac17e36f8&user_key=bar&usage[hits]=1" | ||
}, | ||
"response": { | ||
"status": 200 | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
pkg/tests/tasks/extensions/yaml/3scale-system-service-entry.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
apiVersion: networking.istio.io/v1beta1 | ||
kind: ServiceEntry | ||
metadata: | ||
name: threescale-system | ||
spec: | ||
hosts: | ||
- system.3scale.svc.cluster.local | ||
ports: | ||
- number: 80 | ||
name: http | ||
protocol: HTTP | ||
location: MESH_EXTERNAL | ||
resolution: DNS |
Oops, something went wrong.