From 4e6eea005167ada4693a6598e700d16450737d31 Mon Sep 17 00:00:00 2001 From: huabing zhao Date: Tue, 30 Apr 2024 18:48:26 -0700 Subject: [PATCH 01/13] desing docs for wasm oci support Signed-off-by: huabing zhao --- .../en/contributions/design/wasm-extension.md | 54 ++++++++++++++++++ .../contributions/design/wasm-extension.png | Bin 0 -> 55654 bytes 2 files changed, 54 insertions(+) create mode 100644 site/content/en/contributions/design/wasm-extension.md create mode 100644 site/content/en/contributions/design/wasm-extension.png diff --git a/site/content/en/contributions/design/wasm-extension.md b/site/content/en/contributions/design/wasm-extension.md new file mode 100644 index 0000000000..7ec5d64104 --- /dev/null +++ b/site/content/en/contributions/design/wasm-extension.md @@ -0,0 +1,54 @@ +--- +title: "Wasm OCI Image Support" +--- + +## Motivation +Envoy Gateway (EG) should support Wasm OCI image as a remote wasm code source. +This feature will allow users to deploy Wasm modules from OCI registries, such as Docker Hub, +Google Container Registry, and Amazon Elastic Container Registry, to Envoy proxies managed by EG. + +## Goals +* Define the system components needed to support Wasm OCI images as remote Wasm code sources. + +## Architecture + +![](./wasm-extension.png) + +### Control Plane Wasm File Cache + +Envoy lacks native OCI image support, therefore, EG needs to download Wasm modules from OIC registries, +cache them locally in the file system, and serve them to Envoy over HTTP. + +**HTTP Code Source:** For HTTP code source, we have two options: serve Wasm modules directly from their +original HTTP URLs, or cache them in EG (as with OIC images). Caching both the HTTP Wasm modules and OCI +images inside EG can make UI consistent, for example, sha256sum can be calculated on the EG side and made +optional in the API. EG can also periodically pull Wasm modules and update the local file cache. + +**Memory Optimization:** Since we cache Wasm modules in the file system, we can optimize the memory usage +of the cache and the HTTP server to avoid introducing too much memory consumption by this feature. +For example, when receiving a Wasm pulling request form the Envoy, we can open the Wasm file and write +the file content directly to response, and then close the file. There won’t be significant caching involved. +However, we need to balance the memory usage and the efficiency, which could be addressed in implementation. + +**Caching Mechanism:** Cached files will be evicted based on LRU(Last recently used)algorithm. +If the image’s tag is latest, then they will be updated perodically. The cache clean and update periods +will be configurable. + +## Alternative Considered + +### Inline Bytes + +EG downloads the Wasm modules, caches them in memory, and pushes the Wasm code through xDS as inline bytes. +This could inflate the xDS, potentially causing memory issues for EG and Envoy. + +### Data Plane Agent +Mount Wasm modules in the local file system of the Envoy container. We’ll need an agent deployed in the +same pod as the Envoy for this. It would be too expensive to implement this as we’ll need to intercept +the xDS at the agent. + +### Standalone Wasm HTTP Server +Deploying the Wasm HTTP server as a standalone service. While this has no obvious benefits, it increases +operational costs. + +### Wait for Envoy OCI image support +We could wait indefinitely for Envoy to support OCI imag as a remote wasm code source. diff --git a/site/content/en/contributions/design/wasm-extension.png b/site/content/en/contributions/design/wasm-extension.png new file mode 100644 index 0000000000000000000000000000000000000000..6bac9f46a3f4065a10c762a77c4a1f61fc3c8b69 GIT binary patch literal 55654 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 YS{vWMmOYgh@vH>Zlc$vm6wclFUkn%RPXGV_ literal 0 HcmV?d00001 From 1181ca47e8fb925a699e32f3d7529c8d88d87b29 Mon Sep 17 00:00:00 2001 From: huabing zhao Date: Wed, 1 May 2024 09:19:51 -0700 Subject: [PATCH 02/13] fix lint Signed-off-by: huabing zhao --- site/content/en/contributions/design/wasm-extension.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/content/en/contributions/design/wasm-extension.md b/site/content/en/contributions/design/wasm-extension.md index 7ec5d64104..bf53f95f87 100644 --- a/site/content/en/contributions/design/wasm-extension.md +++ b/site/content/en/contributions/design/wasm-extension.md @@ -12,7 +12,7 @@ Google Container Registry, and Amazon Elastic Container Registry, to Envoy proxi ## Architecture -![](./wasm-extension.png) +![](../wasm-extension.png) ### Control Plane Wasm File Cache From eaff3fad8901c3b206cb739209a8b1dc79a71255 Mon Sep 17 00:00:00 2001 From: Huabing Zhao Date: Wed, 1 May 2024 09:21:37 -0700 Subject: [PATCH 03/13] Update site/content/en/contributions/design/wasm-extension.md Co-authored-by: Arko Dasgupta Signed-off-by: Huabing Zhao --- site/content/en/contributions/design/wasm-extension.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/content/en/contributions/design/wasm-extension.md b/site/content/en/contributions/design/wasm-extension.md index bf53f95f87..00965da471 100644 --- a/site/content/en/contributions/design/wasm-extension.md +++ b/site/content/en/contributions/design/wasm-extension.md @@ -20,7 +20,7 @@ Envoy lacks native OCI image support, therefore, EG needs to download Wasm modul cache them locally in the file system, and serve them to Envoy over HTTP. **HTTP Code Source:** For HTTP code source, we have two options: serve Wasm modules directly from their -original HTTP URLs, or cache them in EG (as with OIC images). Caching both the HTTP Wasm modules and OCI +original HTTP URLs, or cache them in EG (as with OCI images). Caching both the HTTP Wasm modules and OCI images inside EG can make UI consistent, for example, sha256sum can be calculated on the EG side and made optional in the API. EG can also periodically pull Wasm modules and update the local file cache. From 492c33ecf8b77907472ef3c6968fdf07a720b741 Mon Sep 17 00:00:00 2001 From: huabing zhao Date: Wed, 1 May 2024 09:25:58 -0700 Subject: [PATCH 04/13] minor wording Signed-off-by: huabing zhao --- site/content/en/contributions/design/wasm-extension.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/site/content/en/contributions/design/wasm-extension.md b/site/content/en/contributions/design/wasm-extension.md index 00965da471..048e3b2b43 100644 --- a/site/content/en/contributions/design/wasm-extension.md +++ b/site/content/en/contributions/design/wasm-extension.md @@ -22,7 +22,8 @@ cache them locally in the file system, and serve them to Envoy over HTTP. **HTTP Code Source:** For HTTP code source, we have two options: serve Wasm modules directly from their original HTTP URLs, or cache them in EG (as with OCI images). Caching both the HTTP Wasm modules and OCI images inside EG can make UI consistent, for example, sha256sum can be calculated on the EG side and made -optional in the API. EG can also periodically pull Wasm modules and update the local file cache. +optional in the API. This will also make the Envoy proxy side more efficient as it won’t have to download the +Wasm module from the original URL every time, which can be slow. **Memory Optimization:** Since we cache Wasm modules in the file system, we can optimize the memory usage of the cache and the HTTP server to avoid introducing too much memory consumption by this feature. From 2ac9e8f4fe202bf2723380c7e6b16e21a6efdec4 Mon Sep 17 00:00:00 2001 From: huabing zhao Date: Wed, 1 May 2024 09:46:42 -0700 Subject: [PATCH 05/13] authn consideration Signed-off-by: huabing zhao --- site/content/en/contributions/design/wasm-extension.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/site/content/en/contributions/design/wasm-extension.md b/site/content/en/contributions/design/wasm-extension.md index 048e3b2b43..d5fd34ca7f 100644 --- a/site/content/en/contributions/design/wasm-extension.md +++ b/site/content/en/contributions/design/wasm-extension.md @@ -32,9 +32,12 @@ the file content directly to response, and then close the file. There won’t be However, we need to balance the memory usage and the efficiency, which could be addressed in implementation. **Caching Mechanism:** Cached files will be evicted based on LRU(Last recently used)algorithm. -If the image’s tag is latest, then they will be updated perodically. The cache clean and update periods +If the image’s tag is latest, then they will be updated periodically. The cache clean and update periods will be configurable. +**Authentication:** To avoid unauthorized access to the Wasm modules downloaded from private OCI registries, +the communication between the Envoy and EG will be secured using mutual TLS. + ## Alternative Considered ### Inline Bytes From b727e9f814c752f56318f8d4e618726e15b67b25 Mon Sep 17 00:00:00 2001 From: huabing zhao Date: Wed, 1 May 2024 16:45:59 -0700 Subject: [PATCH 06/13] address comments Signed-off-by: huabing zhao --- .../content/en/contributions/design/wasm-extension.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/site/content/en/contributions/design/wasm-extension.md b/site/content/en/contributions/design/wasm-extension.md index d5fd34ca7f..ac44477a66 100644 --- a/site/content/en/contributions/design/wasm-extension.md +++ b/site/content/en/contributions/design/wasm-extension.md @@ -35,8 +35,15 @@ However, we need to balance the memory usage and the efficiency, which could be If the image’s tag is latest, then they will be updated periodically. The cache clean and update periods will be configurable. -**Authentication:** To avoid unauthorized access to the Wasm modules downloaded from private OCI registries, -the communication between the Envoy and EG will be secured using mutual TLS. +**Authn & Authz:** +* To prevent unauthorized proxies from accessing the Wasm modules, the communication between the Envoy and EG will be + secured using mutual TLS. +* To prevent unauthorized users from accessing the Wasm modules, the user who authroize the EEP must have the appropriate + permissions to access the OCI registry. For example, if users in different namespaces (ns1, ns2) access the same OCI image, + each must create a unique secret with registry credentials (secret1 for user1 in ns1, secret2 for user2 in ns2). EG will + validate the provided secret against the OCI registry before serving the Wasm module to the target HTTPRoute/Gateway. +* To prevent unauthorized users from accessing the Wasm modules, the download URL will be appended with a generated secret + suffix that can be validated by the EG. ## Alternative Considered From 491ba0becfae10e89263aba6ac8cd38d7891a843 Mon Sep 17 00:00:00 2001 From: huabing zhao Date: Wed, 1 May 2024 16:47:35 -0700 Subject: [PATCH 07/13] minor wording Signed-off-by: huabing zhao --- site/content/en/contributions/design/wasm-extension.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/content/en/contributions/design/wasm-extension.md b/site/content/en/contributions/design/wasm-extension.md index ac44477a66..74dcf97d12 100644 --- a/site/content/en/contributions/design/wasm-extension.md +++ b/site/content/en/contributions/design/wasm-extension.md @@ -38,7 +38,7 @@ will be configurable. **Authn & Authz:** * To prevent unauthorized proxies from accessing the Wasm modules, the communication between the Envoy and EG will be secured using mutual TLS. -* To prevent unauthorized users from accessing the Wasm modules, the user who authroize the EEP must have the appropriate +* To prevent unauthorized users from accessing the Wasm modules, the user who authorize the EEP must have the appropriate permissions to access the OCI registry. For example, if users in different namespaces (ns1, ns2) access the same OCI image, each must create a unique secret with registry credentials (secret1 for user1 in ns1, secret2 for user2 in ns2). EG will validate the provided secret against the OCI registry before serving the Wasm module to the target HTTPRoute/Gateway. From e48ad93039151ab608df6b58f0f8ddb0593eaee8 Mon Sep 17 00:00:00 2001 From: huabing zhao Date: Wed, 1 May 2024 16:48:11 -0700 Subject: [PATCH 08/13] minor wording Signed-off-by: huabing zhao --- site/content/en/contributions/design/wasm-extension.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/content/en/contributions/design/wasm-extension.md b/site/content/en/contributions/design/wasm-extension.md index 74dcf97d12..f81a3296d9 100644 --- a/site/content/en/contributions/design/wasm-extension.md +++ b/site/content/en/contributions/design/wasm-extension.md @@ -38,7 +38,7 @@ will be configurable. **Authn & Authz:** * To prevent unauthorized proxies from accessing the Wasm modules, the communication between the Envoy and EG will be secured using mutual TLS. -* To prevent unauthorized users from accessing the Wasm modules, the user who authorize the EEP must have the appropriate +* To prevent unauthorized users from accessing the Wasm modules, the user who creates the EEP must have the appropriate permissions to access the OCI registry. For example, if users in different namespaces (ns1, ns2) access the same OCI image, each must create a unique secret with registry credentials (secret1 for user1 in ns1, secret2 for user2 in ns2). EG will validate the provided secret against the OCI registry before serving the Wasm module to the target HTTPRoute/Gateway. From a0cc42cbb7473164db7da644c47838bdb9c51023 Mon Sep 17 00:00:00 2001 From: huabing zhao Date: Wed, 1 May 2024 16:50:49 -0700 Subject: [PATCH 09/13] minor wording Signed-off-by: huabing zhao --- site/content/en/contributions/design/wasm-extension.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/site/content/en/contributions/design/wasm-extension.md b/site/content/en/contributions/design/wasm-extension.md index f81a3296d9..5337c1f560 100644 --- a/site/content/en/contributions/design/wasm-extension.md +++ b/site/content/en/contributions/design/wasm-extension.md @@ -39,9 +39,9 @@ will be configurable. * To prevent unauthorized proxies from accessing the Wasm modules, the communication between the Envoy and EG will be secured using mutual TLS. * To prevent unauthorized users from accessing the Wasm modules, the user who creates the EEP must have the appropriate - permissions to access the OCI registry. For example, if users in different namespaces (ns1, ns2) access the same OCI image, - each must create a unique secret with registry credentials (secret1 for user1 in ns1, secret2 for user2 in ns2). EG will - validate the provided secret against the OCI registry before serving the Wasm module to the target HTTPRoute/Gateway. + permissions to access the OCI registry. For example, if two users create EEPs in different namespaces (ns1, ns2) accessing + the same OCI image, each must also create a unique secret with registry credentials (secret1 for user1 in ns1, secret2 for user2 in ns2). + EG will validate the provided secret against the OCI registry before serving the Wasm module to the target HTTPRoute/Gateway of that EEP. * To prevent unauthorized users from accessing the Wasm modules, the download URL will be appended with a generated secret suffix that can be validated by the EG. From 4f2ad71c8ae1d5b4add98020df99dbb31be7309e Mon Sep 17 00:00:00 2001 From: huabing zhao Date: Wed, 1 May 2024 16:53:18 -0700 Subject: [PATCH 10/13] minor wording Signed-off-by: huabing zhao --- .../en/contributions/design/wasm-extension.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/site/content/en/contributions/design/wasm-extension.md b/site/content/en/contributions/design/wasm-extension.md index 5337c1f560..26f9a10ca2 100644 --- a/site/content/en/contributions/design/wasm-extension.md +++ b/site/content/en/contributions/design/wasm-extension.md @@ -37,13 +37,13 @@ will be configurable. **Authn & Authz:** * To prevent unauthorized proxies from accessing the Wasm modules, the communication between the Envoy and EG will be - secured using mutual TLS. -* To prevent unauthorized users from accessing the Wasm modules, the user who creates the EEP must have the appropriate - permissions to access the OCI registry. For example, if two users create EEPs in different namespaces (ns1, ns2) accessing - the same OCI image, each must also create a unique secret with registry credentials (secret1 for user1 in ns1, secret2 for user2 in ns2). - EG will validate the provided secret against the OCI registry before serving the Wasm module to the target HTTPRoute/Gateway of that EEP. -* To prevent unauthorized users from accessing the Wasm modules, the download URL will be appended with a generated secret - suffix that can be validated by the EG. + secured using mutual TLS. +* To prevent unauthorized access to the Wasm modules, the user who creates the EEP must have the appropriate permissions + to access the OCI registry. For example, if two users create EEPs in different namespaces (ns1, ns2) accessing the same + OCI image, each must also create a unique secret with registry credentials (secret1 for user1 in ns1, secret2 for user2 in ns2). + EG will validate the provided secret against the OCI registry before serving the Wasm module to the target HTTPRoute/Gateway of that EEP. +* To prevent unauthorized access to the Wasm modules, the download URL will be appended with a generated secret suffix + that can be validated by the EG. ## Alternative Considered From 5bca6cc3576682745e347e11e78230541dbdfc85 Mon Sep 17 00:00:00 2001 From: huabing zhao Date: Tue, 7 May 2024 11:08:52 -0700 Subject: [PATCH 11/13] restrict access to priave images Signed-off-by: huabing zhao --- .../en/contributions/design/wasm-extension.md | 36 ++++++++++++------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/site/content/en/contributions/design/wasm-extension.md b/site/content/en/contributions/design/wasm-extension.md index 26f9a10ca2..d7932a5fe0 100644 --- a/site/content/en/contributions/design/wasm-extension.md +++ b/site/content/en/contributions/design/wasm-extension.md @@ -19,31 +19,43 @@ Google Container Registry, and Amazon Elastic Container Registry, to Envoy proxi Envoy lacks native OCI image support, therefore, EG needs to download Wasm modules from OIC registries, cache them locally in the file system, and serve them to Envoy over HTTP. -**HTTP Code Source:** For HTTP code source, we have two options: serve Wasm modules directly from their +#### HTTP Code Source + +For HTTP code source, we have two options: serve Wasm modules directly from their original HTTP URLs, or cache them in EG (as with OCI images). Caching both the HTTP Wasm modules and OCI images inside EG can make UI consistent, for example, sha256sum can be calculated on the EG side and made optional in the API. This will also make the Envoy proxy side more efficient as it won’t have to download the Wasm module from the original URL every time, which can be slow. -**Memory Optimization:** Since we cache Wasm modules in the file system, we can optimize the memory usage +#### Memory Optimization + +Since we cache Wasm modules in the file system, we can optimize the memory usage of the cache and the HTTP server to avoid introducing too much memory consumption by this feature. For example, when receiving a Wasm pulling request form the Envoy, we can open the Wasm file and write the file content directly to response, and then close the file. There won’t be significant caching involved. However, we need to balance the memory usage and the efficiency, which could be addressed in implementation. -**Caching Mechanism:** Cached files will be evicted based on LRU(Last recently used)algorithm. +#### Caching Mechanism + +Cached files will be evicted based on LRU(Last recently used)algorithm. If the image’s tag is latest, then they will be updated periodically. The cache clean and update periods will be configurable. -**Authn & Authz:** -* To prevent unauthorized proxies from accessing the Wasm modules, the communication between the Envoy and EG will be - secured using mutual TLS. -* To prevent unauthorized access to the Wasm modules, the user who creates the EEP must have the appropriate permissions - to access the OCI registry. For example, if two users create EEPs in different namespaces (ns1, ns2) accessing the same - OCI image, each must also create a unique secret with registry credentials (secret1 for user1 in ns1, secret2 for user2 in ns2). - EG will validate the provided secret against the OCI registry before serving the Wasm module to the target HTTPRoute/Gateway of that EEP. -* To prevent unauthorized access to the Wasm modules, the download URL will be appended with a generated secret suffix - that can be validated by the EG. +#### Restrict Access to Private Images + +* **Client Authn with MTLS:** To prevent unauthorized proxies from accessing the Wasm modules, the communication between + the Envoy and EG will be secured using mutual TLS. +* **User Authn with Registry Credentials:** To prevent unauthorized users from accessing the Wasm modules, the user who + creates the EEP must have the appropriate permissions to access the OCI registry. For example, if two users create EEPs + in different namespaces (ns1, ns2) accessing the same OCI image, each must also create a unique secret with registry + credentials (secret1 for user1 in ns1, secret2 for user2 in ns2). EG will validate the provided secret against the OCI + registry before serving the Wasm module to the target HTTPRoute/Gateway of that EEP. +* **Unguessable Download URLs:** It's possible that users who have no permission to access a private OCI image could create + EPPs to bypass the EG permission check. For example, a user could create an EPP, inject a Wasm filter, and put the download + URL of a private OCI image in the Wasm filter configuration. To prevent this, we need to make the download URL unguessable. + The download URL will be generated by EG and will be a random string that is impossible to guess. If a user can get the + config dump the Envoy Proxy, they can still get the download URL. However, they won’t be able to do so without + the permission to access the config dump of Envoy Proxy, which is a more restricted permission (usually Admin role). ## Alternative Considered From 6d76462854a7a44fae3289a091be5efae20821f5 Mon Sep 17 00:00:00 2001 From: Huabing Zhao Date: Wed, 3 Jul 2024 16:05:00 +0800 Subject: [PATCH 12/13] minor change Signed-off-by: Huabing Zhao --- .../en/contributions/design/wasm-extension.md | 35 +++++++++++-------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/site/content/en/contributions/design/wasm-extension.md b/site/content/en/contributions/design/wasm-extension.md index d7932a5fe0..bf47515e50 100644 --- a/site/content/en/contributions/design/wasm-extension.md +++ b/site/content/en/contributions/design/wasm-extension.md @@ -6,6 +6,10 @@ title: "Wasm OCI Image Support" Envoy Gateway (EG) should support Wasm OCI image as a remote wasm code source. This feature will allow users to deploy Wasm modules from OCI registries, such as Docker Hub, Google Container Registry, and Amazon Elastic Container Registry, to Envoy proxies managed by EG. +Deploying Wasm modules from OCI registries has several benefits: +* **Versioning**: Users can use the tag feature of the OCI image to manage the version of the Wasm module. +* **Security**: Users can use private registries to store the Wasm module. +* **Distribution**: Users can use the existing distribution mechanism of the OCI registry to distribute the Wasm module. ## Goals * Define the system components needed to support Wasm OCI images as remote Wasm code sources. @@ -16,7 +20,7 @@ Google Container Registry, and Amazon Elastic Container Registry, to Envoy proxi ### Control Plane Wasm File Cache -Envoy lacks native OCI image support, therefore, EG needs to download Wasm modules from OIC registries, +Envoy lacks native OCI image support, therefore, EG needs to download Wasm modules from their original OIC registries, cache them locally in the file system, and serve them to Envoy over HTTP. #### HTTP Code Source @@ -27,13 +31,16 @@ images inside EG can make UI consistent, for example, sha256sum can be calculate optional in the API. This will also make the Envoy proxy side more efficient as it won’t have to download the Wasm module from the original URL every time, which can be slow. -#### Memory Optimization +#### Resource Consumption -Since we cache Wasm modules in the file system, we can optimize the memory usage +Memory: Since we cache Wasm modules in the file system, we can optimize the memory usage of the cache and the HTTP server to avoid introducing too much memory consumption by this feature. For example, when receiving a Wasm pulling request form the Envoy, we can open the Wasm file and write -the file content directly to response, and then close the file. There won’t be significant caching involved. -However, we need to balance the memory usage and the efficiency, which could be addressed in implementation. +the file content directly to response, and then close the file. There won’t be significant memory consumption involved. + +Disk: Though it's possible to mount a volume to the container for the Wasm file cache, the current implementation just +stores the Wasm files in the EG container’s file system. The disk space consumed by the cache is limited to 1GB by default, +it can be made configurable in the future. #### Caching Mechanism @@ -43,19 +50,19 @@ will be configurable. #### Restrict Access to Private Images -* **Client Authn with MTLS:** To prevent unauthorized proxies from accessing the Wasm modules, the communication between - the Envoy and EG will be secured using mutual TLS. +* **Client Authn with mTLS:** To prevent unauthorized proxies from accessing the Wasm modules, the communication between + the Envoy and EG will be secured using mTLS. * **User Authn with Registry Credentials:** To prevent unauthorized users from accessing the Wasm modules, the user who creates the EEP must have the appropriate permissions to access the OCI registry. For example, if two users create EEPs in different namespaces (ns1, ns2) accessing the same OCI image, each must also create a unique secret with registry - credentials (secret1 for user1 in ns1, secret2 for user2 in ns2). EG will validate the provided secret against the OCI - registry before serving the Wasm module to the target HTTPRoute/Gateway of that EEP. + credentials (secret1 for user1 in ns1, secret2 for user2 in ns2) and provide it in the EEP configuration. EG will validate + the provided secret against the OCI registry before serving the Wasm module to the target HTTPRoute/Gateway of that EEP. * **Unguessable Download URLs:** It's possible that users who have no permission to access a private OCI image could create - EPPs to bypass the EG permission check. For example, a user could create an EPP, inject a Wasm filter, and put the download - URL of a private OCI image in the Wasm filter configuration. To prevent this, we need to make the download URL unguessable. - The download URL will be generated by EG and will be a random string that is impossible to guess. If a user can get the - config dump the Envoy Proxy, they can still get the download URL. However, they won’t be able to do so without - the permission to access the config dump of Envoy Proxy, which is a more restricted permission (usually Admin role). + an EnvoyPatchPolicy to bypass the EG permission check. For example, a user could create an EPP, inject a Wasm filter, + and put the download URL of a private OCI image in the Wasm filter configuration. To prevent this, we need to make the + download URL unguessable. The download URL will be generated by EG and will be a random string that is impossible to + guess. If a user can get the config dump the Envoy Proxy, they can still get the download URL. However, they won’t be + able to do so without the permission to access the config dump of Envoy Proxy, which is a more restricted permission (usually Admin role). ## Alternative Considered From 6e72cd6a98a2bb1d011ad109c249afa29c41c0ea Mon Sep 17 00:00:00 2001 From: Huabing Zhao Date: Tue, 9 Jul 2024 09:08:03 +0800 Subject: [PATCH 13/13] move image to /img Signed-off-by: Huabing Zhao --- .../en/contributions/design/wasm-extension.md | 2 +- .../design => static/img}/wasm-extension.png | Bin 2 files changed, 1 insertion(+), 1 deletion(-) rename site/{content/en/contributions/design => static/img}/wasm-extension.png (100%) diff --git a/site/content/en/contributions/design/wasm-extension.md b/site/content/en/contributions/design/wasm-extension.md index bf47515e50..8700fcecbd 100644 --- a/site/content/en/contributions/design/wasm-extension.md +++ b/site/content/en/contributions/design/wasm-extension.md @@ -16,7 +16,7 @@ Deploying Wasm modules from OCI registries has several benefits: ## Architecture -![](../wasm-extension.png) +![](/img/wasm-extension.png) ### Control Plane Wasm File Cache diff --git a/site/content/en/contributions/design/wasm-extension.png b/site/static/img/wasm-extension.png similarity index 100% rename from site/content/en/contributions/design/wasm-extension.png rename to site/static/img/wasm-extension.png