From 74e5750386e0c9a08ae1933ac260b5c579f466cb Mon Sep 17 00:00:00 2001 From: Huabing Zhao Date: Tue, 29 Oct 2024 09:17:17 +0800 Subject: [PATCH] Fix: xds translation failed when wasm http code source configured without sha (#4547) * fix wasm http code source without sha Signed-off-by: Huabing Zhao * release note Signed-off-by: Huabing Zhao * fix gen Signed-off-by: Huabing Zhao * fix gen Signed-off-by: Huabing Zhao --------- Signed-off-by: Huabing Zhao --- internal/gatewayapi/envoyextensionpolicy.go | 6 +- .../testdata/custom-filter-order.in.yaml | 4 +- .../testdata/custom-filter-order.out.yaml | 8 +- ...tensionpolicy-with-wasm-targetrefs.in.yaml | 4 +- ...ensionpolicy-with-wasm-targetrefs.out.yaml | 12 +-- .../envoyextensionpolicy-with-wasm.in.yaml | 6 +- .../envoyextensionpolicy-with-wasm.out.yaml | 10 +- internal/gatewayapi/translator_test.go | 5 +- release-notes/current.yaml | 1 + test/e2e/testdata/wasm-http.yaml | 36 ++++++++ test/e2e/tests/wasm_http.go | 92 ++++++++++--------- 11 files changed, 117 insertions(+), 67 deletions(-) diff --git a/internal/gatewayapi/envoyextensionpolicy.go b/internal/gatewayapi/envoyextensionpolicy.go index 4abc9a69046..9ba561f1b5d 100644 --- a/internal/gatewayapi/envoyextensionpolicy.go +++ b/internal/gatewayapi/envoyextensionpolicy.go @@ -561,6 +561,8 @@ func (t *Translator) buildWasm( switch config.Code.Type { case egv1a1.HTTPWasmCodeSourceType: + var checksum string + // This is a sanity check, the validation should have caught this if config.Code.HTTP == nil { return nil, fmt.Errorf("missing HTTP field in Wasm code source") @@ -572,7 +574,7 @@ func (t *Translator) buildWasm( http := config.Code.HTTP - if servingURL, _, err = t.WasmCache.Get(http.URL, wasm.GetOptions{ + if servingURL, checksum, err = t.WasmCache.Get(http.URL, wasm.GetOptions{ Checksum: originalChecksum, PullPolicy: pullPolicy, ResourceName: irConfigNameForWasm(policy, idx), @@ -584,7 +586,7 @@ func (t *Translator) buildWasm( code = &ir.HTTPWasmCode{ ServingURL: servingURL, OriginalURL: http.URL, - SHA256: originalChecksum, + SHA256: checksum, } case egv1a1.ImageWasmCodeSourceType: diff --git a/internal/gatewayapi/testdata/custom-filter-order.in.yaml b/internal/gatewayapi/testdata/custom-filter-order.in.yaml index 99b46e6de82..6f27637135c 100644 --- a/internal/gatewayapi/testdata/custom-filter-order.in.yaml +++ b/internal/gatewayapi/testdata/custom-filter-order.in.yaml @@ -111,7 +111,7 @@ envoyextensionpolicies: type: HTTP http: url: https://www.example.com/wasm-filter-1.wasm - sha256: 746df05c8f3a0b07a46c0967cfbc5cbe5b9d48d0f79b6177eeedf8be6c8b34b5 + sha256: 2d89c4c6ab2a1c615c7696ed37ade9e50654ac70384b5d45100eb08e62130ff4 config: parameter1: key1: value1 @@ -122,7 +122,7 @@ envoyextensionpolicies: type: HTTP http: url: https://www.example.com/wasm-filter-2.wasm - sha256: a1efca12ea51069abb123bf9c77889fcc2a31cc5483fc14d115e44fdf07c7980 + sha256: 84274ca23246855cc491b3c6a657a89167e0b109a7ae380f1e64df77c910307e config: parameter1: value1 parameter2: value2 diff --git a/internal/gatewayapi/testdata/custom-filter-order.out.yaml b/internal/gatewayapi/testdata/custom-filter-order.out.yaml index 6967bf280f3..043eeab1543 100644 --- a/internal/gatewayapi/testdata/custom-filter-order.out.yaml +++ b/internal/gatewayapi/testdata/custom-filter-order.out.yaml @@ -13,7 +13,7 @@ envoyExtensionPolicies: wasm: - code: http: - sha256: 746df05c8f3a0b07a46c0967cfbc5cbe5b9d48d0f79b6177eeedf8be6c8b34b5 + sha256: 2d89c4c6ab2a1c615c7696ed37ade9e50654ac70384b5d45100eb08e62130ff4 url: https://www.example.com/wasm-filter-1.wasm type: HTTP config: @@ -24,7 +24,7 @@ envoyExtensionPolicies: name: wasm-filter-1 - code: http: - sha256: a1efca12ea51069abb123bf9c77889fcc2a31cc5483fc14d115e44fdf07c7980 + sha256: 84274ca23246855cc491b3c6a657a89167e0b109a7ae380f1e64df77c910307e url: https://www.example.com/wasm-filter-2.wasm type: HTTP config: @@ -257,7 +257,7 @@ xdsIR: httpWasmCode: originalDownloadingURL: https://www.example.com/wasm-filter-1.wasm servingURL: https://envoy-gateway:18002/5c90b9a82642ce00a7753923fabead306b9d9a54a7c0bd2463a1af3efcfb110b.wasm - sha256: 746df05c8f3a0b07a46c0967cfbc5cbe5b9d48d0f79b6177eeedf8be6c8b34b5 + sha256: 2d89c4c6ab2a1c615c7696ed37ade9e50654ac70384b5d45100eb08e62130ff4 name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/0 wasmName: wasm-filter-1 - config: @@ -267,7 +267,7 @@ xdsIR: httpWasmCode: originalDownloadingURL: https://www.example.com/wasm-filter-2.wasm servingURL: https://envoy-gateway:18002/593e4cc60a7e0fa4d4f86531a5e20e785213a52000f056a7a8b5c5afcb908052.wasm - sha256: a1efca12ea51069abb123bf9c77889fcc2a31cc5483fc14d115e44fdf07c7980 + sha256: 84274ca23246855cc491b3c6a657a89167e0b109a7ae380f1e64df77c910307e name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/1 wasmName: wasm-filter-2 hostname: www.example.com diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-wasm-targetrefs.in.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-wasm-targetrefs.in.yaml index 106267da645..17026ebbad6 100644 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-wasm-targetrefs.in.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-wasm-targetrefs.in.yaml @@ -72,7 +72,7 @@ envoyextensionpolicies: type: HTTP http: url: https://www.example.com/wasm-filter-1.wasm - sha256: 746df05c8f3a0b07a46c0967cfbc5cbe5b9d48d0f79b6177eeedf8be6c8b34b5 + sha256: 2d89c4c6ab2a1c615c7696ed37ade9e50654ac70384b5d45100eb08e62130ff4 config: parameter1: key1: value1 @@ -83,7 +83,7 @@ envoyextensionpolicies: type: HTTP http: url: https://www.example.com/wasm-filter-2.wasm - sha256: a1efca12ea51069abb123bf9c77889fcc2a31cc5483fc14d115e44fdf07c7980 + sha256: 84274ca23246855cc491b3c6a657a89167e0b109a7ae380f1e64df77c910307e config: parameter1: value1 parameter2: value2 diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-wasm-targetrefs.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-wasm-targetrefs.out.yaml index 4abc9f59092..8c65fb9cf65 100644 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-wasm-targetrefs.out.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-wasm-targetrefs.out.yaml @@ -16,7 +16,7 @@ envoyExtensionPolicies: wasm: - code: http: - sha256: 746df05c8f3a0b07a46c0967cfbc5cbe5b9d48d0f79b6177eeedf8be6c8b34b5 + sha256: 2d89c4c6ab2a1c615c7696ed37ade9e50654ac70384b5d45100eb08e62130ff4 url: https://www.example.com/wasm-filter-1.wasm type: HTTP config: @@ -27,7 +27,7 @@ envoyExtensionPolicies: name: wasm-filter-1 - code: http: - sha256: a1efca12ea51069abb123bf9c77889fcc2a31cc5483fc14d115e44fdf07c7980 + sha256: 84274ca23246855cc491b3c6a657a89167e0b109a7ae380f1e64df77c910307e url: https://www.example.com/wasm-filter-2.wasm type: HTTP config: @@ -239,7 +239,7 @@ xdsIR: httpWasmCode: originalDownloadingURL: https://www.example.com/wasm-filter-1.wasm servingURL: https://envoy-gateway:18002/5c90b9a82642ce00a7753923fabead306b9d9a54a7c0bd2463a1af3efcfb110b.wasm - sha256: 746df05c8f3a0b07a46c0967cfbc5cbe5b9d48d0f79b6177eeedf8be6c8b34b5 + sha256: 2d89c4c6ab2a1c615c7696ed37ade9e50654ac70384b5d45100eb08e62130ff4 name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/0 wasmName: wasm-filter-1 - config: @@ -249,7 +249,7 @@ xdsIR: httpWasmCode: originalDownloadingURL: https://www.example.com/wasm-filter-2.wasm servingURL: https://envoy-gateway:18002/593e4cc60a7e0fa4d4f86531a5e20e785213a52000f056a7a8b5c5afcb908052.wasm - sha256: a1efca12ea51069abb123bf9c77889fcc2a31cc5483fc14d115e44fdf07c7980 + sha256: 84274ca23246855cc491b3c6a657a89167e0b109a7ae380f1e64df77c910307e name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/1 wasmName: wasm-filter-2 hostname: www.example.com @@ -280,7 +280,7 @@ xdsIR: httpWasmCode: originalDownloadingURL: https://www.example.com/wasm-filter-1.wasm servingURL: https://envoy-gateway:18002/5c90b9a82642ce00a7753923fabead306b9d9a54a7c0bd2463a1af3efcfb110b.wasm - sha256: 746df05c8f3a0b07a46c0967cfbc5cbe5b9d48d0f79b6177eeedf8be6c8b34b5 + sha256: 2d89c4c6ab2a1c615c7696ed37ade9e50654ac70384b5d45100eb08e62130ff4 name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/0 wasmName: wasm-filter-1 - config: @@ -290,7 +290,7 @@ xdsIR: httpWasmCode: originalDownloadingURL: https://www.example.com/wasm-filter-2.wasm servingURL: https://envoy-gateway:18002/593e4cc60a7e0fa4d4f86531a5e20e785213a52000f056a7a8b5c5afcb908052.wasm - sha256: a1efca12ea51069abb123bf9c77889fcc2a31cc5483fc14d115e44fdf07c7980 + sha256: 84274ca23246855cc491b3c6a657a89167e0b109a7ae380f1e64df77c910307e name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/1 wasmName: wasm-filter-2 hostname: www.example.com diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-wasm.in.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-wasm.in.yaml index 5cb2b192553..e7414013410 100644 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-wasm.in.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-wasm.in.yaml @@ -77,7 +77,7 @@ envoyextensionpolicies: type: HTTP http: url: https://www.example.com/wasm-filter-1.wasm - sha256: 746df05c8f3a0b07a46c0967cfbc5cbe5b9d48d0f79b6177eeedf8be6c8b34b5 + sha256: 2d89c4c6ab2a1c615c7696ed37ade9e50654ac70384b5d45100eb08e62130ff4 config: parameter1: key1: value1 @@ -91,7 +91,7 @@ envoyextensionpolicies: url: oci://www.example.com/wasm-filter-2:v1.0.0 pullSecretRef: name: my-pull-secret - sha256: a1efca12ea51069abb123bf9c77889fcc2a31cc5483fc14d115e44fdf07c7980 + sha256: 314100af781b98a8ca175d5bf90a8bf76576e20a2f397a88223404edc6ebfd46 config: parameter1: value1 parameter2: value2 @@ -115,7 +115,7 @@ envoyextensionpolicies: type: HTTP http: url: https://www.test.com/wasm-filter-4.wasm - sha256: a1f0b78b8c1320690327800e3a5de10e7dbba7b6c752e702193a395a52c727b6 + sha256: b6922722ab58109abfaa8d9eb16f339b38b2bb1c17076b083b34438b934e7463 config: parameter1: key1: value1 diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-wasm.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-wasm.out.yaml index 68cfaf92515..368c32a4055 100644 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-wasm.out.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-wasm.out.yaml @@ -13,7 +13,7 @@ envoyExtensionPolicies: wasm: - code: http: - sha256: a1f0b78b8c1320690327800e3a5de10e7dbba7b6c752e702193a395a52c727b6 + sha256: b6922722ab58109abfaa8d9eb16f339b38b2bb1c17076b083b34438b934e7463 url: https://www.test.com/wasm-filter-4.wasm type: HTTP config: @@ -53,7 +53,7 @@ envoyExtensionPolicies: wasm: - code: http: - sha256: 746df05c8f3a0b07a46c0967cfbc5cbe5b9d48d0f79b6177eeedf8be6c8b34b5 + sha256: 2d89c4c6ab2a1c615c7696ed37ade9e50654ac70384b5d45100eb08e62130ff4 url: https://www.example.com/wasm-filter-1.wasm type: HTTP config: @@ -68,7 +68,7 @@ envoyExtensionPolicies: group: null kind: null name: my-pull-secret - sha256: a1efca12ea51069abb123bf9c77889fcc2a31cc5483fc14d115e44fdf07c7980 + sha256: 314100af781b98a8ca175d5bf90a8bf76576e20a2f397a88223404edc6ebfd46 url: oci://www.example.com/wasm-filter-2:v1.0.0 type: Image config: @@ -277,7 +277,7 @@ xdsIR: httpWasmCode: originalDownloadingURL: https://www.test.com/wasm-filter-4.wasm servingURL: https://envoy-gateway:18002/fe571e7b1ef5dc626ceb2c2c86782a134a92989a2643485238951696ae4334c3.wasm - sha256: a1f0b78b8c1320690327800e3a5de10e7dbba7b6c752e702193a395a52c727b6 + sha256: b6922722ab58109abfaa8d9eb16f339b38b2bb1c17076b083b34438b934e7463 name: envoyextensionpolicy/default/policy-for-http-route/wasm/0 wasmName: wasm-filter-4 hostname: www.example.com @@ -311,7 +311,7 @@ xdsIR: httpWasmCode: originalDownloadingURL: https://www.example.com/wasm-filter-1.wasm servingURL: https://envoy-gateway:18002/5c90b9a82642ce00a7753923fabead306b9d9a54a7c0bd2463a1af3efcfb110b.wasm - sha256: 746df05c8f3a0b07a46c0967cfbc5cbe5b9d48d0f79b6177eeedf8be6c8b34b5 + sha256: 2d89c4c6ab2a1c615c7696ed37ade9e50654ac70384b5d45100eb08e62130ff4 name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/0 wasmName: wasm-filter-1 - config: diff --git a/internal/gatewayapi/translator_test.go b/internal/gatewayapi/translator_test.go index 7184326fd62..39200342a5f 100644 --- a/internal/gatewayapi/translator_test.go +++ b/internal/gatewayapi/translator_test.go @@ -833,7 +833,7 @@ type mockWasmCache struct{} func (m *mockWasmCache) Start(_ context.Context) {} -func (m *mockWasmCache) Get(downloadURL string, _ wasm.GetOptions) (url string, checksum string, err error) { +func (m *mockWasmCache) Get(downloadURL string, options wasm.GetOptions) (url string, checksum string, err error) { // This is a mock implementation of the wasm.Cache.Get method. sha := sha256.Sum256([]byte(downloadURL)) hashedName := hex.EncodeToString(sha[:]) @@ -841,6 +841,9 @@ func (m *mockWasmCache) Get(downloadURL string, _ wasm.GetOptions) (url string, salt = append(salt, hashedName...) sha = sha256.Sum256(salt) checksum = hex.EncodeToString(sha[:]) + if options.Checksum != "" && checksum != options.Checksum { + return "", "", fmt.Errorf("module downloaded from %v has checksum %v, which does not match: %v", downloadURL, checksum, options.Checksum) + } return fmt.Sprintf("https://envoy-gateway:18002/%s.wasm", hashedName), checksum, nil } diff --git a/release-notes/current.yaml b/release-notes/current.yaml index 8240c9ab163..cf4ea00691b 100644 --- a/release-notes/current.yaml +++ b/release-notes/current.yaml @@ -15,6 +15,7 @@ new features: | # Fixes for bugs identified in previous versions. bug fixes: | Only log endpoint configuration in verbose logging mode (`-v 4` or higher) + The xDS translation failed when wasm http code source configured without a sha # Enhancements that improve performance. performance improvements: | diff --git a/test/e2e/testdata/wasm-http.yaml b/test/e2e/testdata/wasm-http.yaml index 2bc1aae0ab3..856d381a517 100644 --- a/test/e2e/testdata/wasm-http.yaml +++ b/test/e2e/testdata/wasm-http.yaml @@ -19,6 +19,24 @@ spec: --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute +metadata: + name: http-with-http-wasm-source-no-sha + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace + hostnames: ["www.example.com"] + rules: + - matches: + - path: + type: PathPrefix + value: /wasm-http-no-sha + backendRefs: + - name: infra-backend-v1 + port: 8080 +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute metadata: name: http-without-wasm namespace: gateway-conformance-infra @@ -53,3 +71,21 @@ spec: http: url: https://raw.githubusercontent.com/envoyproxy/examples/main/wasm-cc/lib/envoy_filter_http_wasm_example.wasm sha256: 79c9f85128bb0177b6511afa85d587224efded376ac0ef76df56595f1e6315c0 +--- +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: EnvoyExtensionPolicy +metadata: + name: http-wasm-source-test-no-sha + namespace: gateway-conformance-infra +spec: + targetRefs: + - group: gateway.networking.k8s.io + kind: HTTPRoute + name: http-with-http-wasm-source-no-sha + wasm: + - name: wasm-filter + rootID: my_root_id + code: + type: HTTP + http: + url: https://raw.githubusercontent.com/envoyproxy/examples/main/wasm-cc/lib/envoy_filter_http_wasm_example.wasm diff --git a/test/e2e/tests/wasm_http.go b/test/e2e/tests/wasm_http.go index e5ef2e14c82..7f7da0c833b 100644 --- a/test/e2e/tests/wasm_http.go +++ b/test/e2e/tests/wasm_http.go @@ -32,49 +32,11 @@ var HTTPWasmTest = suite.ConformanceTest{ Manifests: []string{"testdata/wasm-http.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { t.Run("http route with http wasm source", func(t *testing.T) { - ns := "gateway-conformance-infra" - routeNN := types.NamespacedName{Name: "http-with-http-wasm-source", Namespace: ns} - gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} - gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) - - ancestorRef := gwapiv1a2.ParentReference{ - Group: gatewayapi.GroupPtr(gwapiv1.GroupName), - Kind: gatewayapi.KindPtr(resource.KindGateway), - Namespace: gatewayapi.NamespacePtr(gwNN.Namespace), - Name: gwapiv1.ObjectName(gwNN.Name), - } - EnvoyExtensionPolicyMustBeAccepted(t, suite.Client, types.NamespacedName{Name: "http-wasm-source-test", Namespace: ns}, suite.ControllerName, ancestorRef) - - expectedResponse := http.ExpectedResponse{ - Request: http.Request{ - Host: "www.example.com", - Path: "/wasm-http", - }, - - // Set the expected request properties to empty strings. - // This is a workaround to avoid the test failure. - // These values can't be extracted from the json format response - // body because the test wasm code appends a "Hello, world" text - // to the response body, invalidating the json format. - ExpectedRequest: &http.ExpectedRequest{ - Request: http.Request{ - Host: "", - Method: "", - Path: "", - Headers: nil, - }, - }, - Namespace: "", - - Response: http.Response{ - StatusCode: 200, - Headers: map[string]string{ - "x-wasm-custom": "FOO", // response header added by wasm - }, - }, - } + testWasmHTTPCodeSource(t, suite, "http-with-http-wasm-source", "http-wasm-source-test", "/wasm-http") + }) - http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, expectedResponse) + t.Run("http route with http wasm source no sha", func(t *testing.T) { + testWasmHTTPCodeSource(t, suite, "http-with-http-wasm-source-no-sha", "http-wasm-source-test-no-sha", "/wasm-http-no-sha") }) t.Run("http route without wasm", func(t *testing.T) { @@ -115,3 +77,49 @@ var HTTPWasmTest = suite.ConformanceTest{ }) }, } + +func testWasmHTTPCodeSource(t *testing.T, suite *suite.ConformanceTestSuite, route, eep, path string) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: route, Namespace: ns} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} + gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) + + ancestorRef := gwapiv1a2.ParentReference{ + Group: gatewayapi.GroupPtr(gwapiv1.GroupName), + Kind: gatewayapi.KindPtr(resource.KindGateway), + Namespace: gatewayapi.NamespacePtr(gwNN.Namespace), + Name: gwapiv1.ObjectName(gwNN.Name), + } + EnvoyExtensionPolicyMustBeAccepted(t, suite.Client, types.NamespacedName{Name: eep, Namespace: ns}, suite.ControllerName, ancestorRef) + + expectedResponse := http.ExpectedResponse{ + Request: http.Request{ + Host: "www.example.com", + Path: path, + }, + + // Set the expected request properties to empty strings. + // This is a workaround to avoid the test failure. + // These values can't be extracted from the json format response + // body because the test wasm code appends a "Hello, world" text + // to the response body, invalidating the json format. + ExpectedRequest: &http.ExpectedRequest{ + Request: http.Request{ + Host: "", + Method: "", + Path: "", + Headers: nil, + }, + }, + Namespace: "", + + Response: http.Response{ + StatusCode: 200, + Headers: map[string]string{ + "x-wasm-custom": "FOO", // response header added by wasm + }, + }, + } + + http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, expectedResponse) +}