Cluster Access
Acccessing the cluster
Some Flight implementations may require generating random data, which is useful for tasks like creating initial passwords or generating cryptographic certificates. However, this approach has a drawback: the inability to reproduce the same values across runs. This can lead to unnecessary churn when deploying updated releases.
One of the key advantages of using WebAssembly (Wasm) is its secure sandboxing, which ensures package implementations run in isolation without direct access to external systems. Since Wasm is merely an assembly instruction set, it can only perform numeric computations by itself.
To extend Wasm’s capabilities, we use the WebAssembly System Interface (WASI), which allows external calls from the WebAssembly module to the host. Yoke leverages WASI to expose a single function: k8s_lookup.
This function enables Flights to look up Kubernetes resources, but only those owned by the target release. This allows packages to reuse values from previous iterations, reducing unnecessary churn, rollouts, and downtime during updates.
This feature is opt-in during takeoff:
yoke takeoff --cluster-access foo bar.wasm
Example Usage
The k8s_lookup function is a low-level host export, and users are not expected to call it directly. Instead, Yoke provides a Go package that wraps it in a more user-friendly API: github.com/yokecd/yoke/pkg/flight/wasi/k8s.
For other languages, contributors are welcome to reference the implementation or request official support for their preferred ecosystem.
A Go-based example can be found here.
package main
import ( "crypto/rand" "encoding/json" "fmt" "os"
corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/yokecd/yoke/pkg/flight" "github.com/yokecd/yoke/pkg/flight/wasi/k8s")
func main() { if err := run(); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) }}
func run() error { secretName := flight.Release() + "-example"
secret, err := k8s.Lookup[corev1.Secret](k8s.ResourceIdentifier{ ApiVersion: "v1", Kind: "Secret", Name: secretName, Namespace: flight.Namespace(), }) if err != nil && !k8s.IsErrNotFound(err) { return fmt.Errorf("failed to lookup secret: %v", err) }
return json.NewEncoder(os.Stdout).Encode(corev1.Secret{ TypeMeta: metav1.TypeMeta{ APIVersion: "v1", Kind: "Secret", }, ObjectMeta: metav1.ObjectMeta{ Name: secretName, }, StringData: map[string]string{ "password": func() string { if secret != nil { // if the secret already exists we want to reuse the example value instead of generating a new random string. return string(secret.Data["password"]) } // Since the secret does not exist we need to generate a new password via the power of entropy! return RandomString() }(), }, })}
func RandomString() string { buf := make([]byte, 6) rand.Read(buf) return fmt.Sprintf("%x", buf)}
Resource Access Matchers
Yoke is highly security-minded when it comes to cluster access. By default, resource lookups are disabled—you cannot query any cluster resources unless access is explicitly enabled. Furthermore, you cannot access resources that are not managed by your release. While this behavior is generally beneficial, there may be situations where you need to reference cluster state that lies outside your release’s scope.
To support this, Yoke provides Resource Access Matchers, which allow you to specify exactly which resources should be accessible. These matchers can be as granular as necessary; targeting specific resources or as broad as desired, granting access to all resources within a cluster or namespace.
Resource Access Matcher Format
Resource Access Matchers are strings with the following format: $namespace/$groupkind:$name
- Both
namespace
andname
are optional; if omitted, they default to*
, which matches anything. groupkind
is required but can also be set to*
to match any group and kind.- The
groupkind
string follows Kubernetes’ canonical format:kind.group
.
Example Matchers:
* # matches any resourcedefault/* # matches any resource in namespace defaultDeployment.apps # matches all Deployments in the group "apps"default/Deployment.apps:example # matches deployment named example in namespace default
Matcher usage:
When using the Yoke CLI:
# Multiple resource matcher strings can be provided.# Repeat the flag or separate them with commas.yoke takeoff -resource-access=infra/Configmap:global -resource-access=...
When using Airways:
apiVersion: yoke.cd/v1alpha1kind: Airwaymetadata: ...spec: resourceAccessMatchers: - infra/Configmap:global - ... ...
A Note on Security
Security-conscious users may wonder whether granting Flights access to the cluster introduces a vulnerability. However, Wasm modules do not have direct access to the cluster. Instead, they interact with the host Yoke program, which retrieves the requested resource and returns its JSON representation to the module’s memory. The Wasm module itself cannot open sockets, file descriptors, or network connections.
That said, this feature remains opt-in and is recommended for use only with trusted Flights.