You can use WebAssembly extensions to add new features directly into the Red Hat OpenShift Service Mesh proxies, allowing you to move even more common functionality out of your applications, and implement them in a single language that compiles to WebAssembly bytecode.

WebAssembly extensions

WebAssembly modules can be run on many platforms, including proxies, and has broad language support, fast execution and a sandboxed-by-default security model.

Extension Capabilities

Red Hat OpenShift Service Mesh extensions are Envoy HTTP Filters, giving them a wide range of capabilities:

  • Manipulating the body and headers of requests and responses

  • Out-of-band HTTP requests to services not in the request path, such as authentication or policy checking

  • Side-channel data storage and queues for filters to communicate with each other

There are two parts to writing a Red Hat OpenShift Service Mesh extension: you’ll have to write your extension using an SDK that exposes the proxy-wasm API and compile it to a WebAssembly module, and then package it into a container.

Supported languages

You can use any language that compiles to WebAssembly bytecode to write a Red Hat OpenShift Service Mesh extension, but the following languages have existing SDKs that expose the proxy-wasm API so that it can be consumed directly.

Table 1. Supported languages
Language Maintainer Repository

AssemblyScript

solo.io

solo-io/proxy-runtime

C++

proxy-wasm team (Istio Community)

proxy-wasm/proxy-wasm-cpp-sdk

Go

tetrate.io

tetratelabs/proxy-wasm-go-sdk

Rust

proxy-wasm team (Istio Community)

proxy-wasm/proxy-wasm-rust-sdk

Container Format

You must have a .wasm file containing the bytecode of your WebAssembly module, and a manifest.yaml file in the root of the container filesystem to make your container image a valid extension image.

manifest.yaml
schemaVersion: 1

name: <your-extension>
description: <description>
version: 1.0.0
phase: PreAuthZ
priority: 100
module: extension.wasm
Table 2. manifest.yml Field Reference
Field Description

schemaVersion

Used for versioning of the manifest schema. Currently the only possible value is 1.

name

The name of your extension. This field is just metadata and currently unused.

description

The description of your extension. This field is just metadata and currently unused.

version

The version of your extension. This field is just metadata and currently unused.

phase

The default execution phase of your extension. This is a required field.

priority

The default priority of your extension. This is a required field.

module

The relative path from the container filesystem’s root to your WebAssembly module. This is a required field.

Example Rust extension

For a complete example that was built using the Rust SDK, take a look at the header-append-filter. It is a very simple filter that appends a header, custom-header, to all responses, with the value depending on its configuration.

Enabling WebAssembly extension support

Support for WebAssembly extensions to Red Hat OpenShift Service Mesh is currently in Tech Preview, so it must be explicitly enabled for your ServiceMeshControlPlane. Set spec.techPreview.wasmExtensions.enabled in your SMCPv2 to true. Here’s an example:

apiVersion: maistra.io/v2
kind: ServiceMeshControlPlane
metadata:
  name: openid-connect
  namespace: istio-system
spec:
  techPreview:
    wasmExtensions:
      enabled: true

Deploying extensions

Red Hat OpenShift Service Mesh extensions can be enabled using the ServiceMeshExtension resource. The following snippet is an example resource.

apiVersion: maistra.io/v1alpha1
kind: ServiceMeshExtension
metadata:
  name: header-append
  namespace: istio-system
spec:
  workloadSelector:
    labels:
      app: httpbin
  config: test
  image: quay.io/maistra-dev/header-append-filter:latest
  phase: PostAuthZ
  priority: 100
Table 3. ServiceMeshExtension Field Reference
Field Description

metadata.namespace

The metadata.namespace of a ServiceMeshExtension source has a special semantic: if it equals the Control Plane Namespace, the extension will be applied to all workloads in the Service Mesh that match its workloadSelector. When deployed to any other Mesh Namespace, it will only be applied to workloads in that same Namespace.

spec.workloadSelector

The spec.workloadSelector field has the same semantic as the spec.selector field of the Istio Gateway resource. It will match a workload based on its Pod labels. If no workloadSelector is specified, the extension will be applied to all workloads in the namespace.

spec.config

This is a pass-through string field that will be handed over to the extension, so syntax and semantics are dependant on the extension you’re deploying.

spec.image

A container image URI pointing to the image that holds the extension.

spec.phase

This field defaults to the value set in the manifest.yaml of the extension, but can be overwritten by the user. The phase determines where in the filter chain the extension is injected, in relation to existing Istio functionality like Authentication, Authorization and metrics generation. Valid values are: PreAuthN, PostAuthN, PreAuthZ, PostAuthZ, PreStats, PostStats. This field defaults to the value set in the manifest.yaml of the extension, but can be overwritten by the user.

spec.priority

If multiple extensions with the same spec.phase are applied to the same workload instance, the spec.priority determines the ordering of execution. Extensions with higher priority will be executed first. This allows for inter-dependent extensions. This field defaults to the value set in the manifest.yaml of the extension, but can be overwritten by the user.