Issuing Identity with MeshIdentity bundled provider
This is a guide for experimental feature.
The MeshIdentity allows you to issue identity for selected data planes. This approach is SPIFFE compliant and can be used with Spire. In this guide we will take a look on how to issue identities using bundled provider.
Prerequisites
Before you begin, make sure you have the following tools installed:
- Helm – used to install and manage Kubernetes applications
- minikube – used to run a local Kubernetes cluster for testing
Start a Kubernetes cluster
Start a local Kubernetes cluster using minikube. The -p
flag creates a new profile named mesh-zone
:
minikube start -p mesh-zone
If you already have a running Kubernetes cluster, either locally or in the cloud (for example, EKS, GKE, or AKS), you can skip this step.
Install Kuma
Install Kuma control plane with Helm by executing:
helm repo add kuma https://kumahq.github.io/charts
helm repo update
helm install --create-namespace --namespace kuma-system kuma kuma/kuma
Deploy demo application
- Deploy the application
kubectl apply -f https://raw.githubusercontent.com/kumahq/kuma-counter-demo/refs/heads/main/k8s/000-with-kuma.yaml kubectl wait -n kuma-demo --for=condition=ready pod --selector=app=demo-app --timeout=90s
For the MeshIdentity
to work you need to have meshServices.mode: Exclusive
set on Mesh resource. It is already configured
in demo.
-
Port-forward the service to the namespace on port 5000:
kubectl port-forward svc/demo-app -n kuma-demo 5050:5050
-
Try making requests to demo-app
curl -XPOST localhost:5050/api/counter
You should see similar results:
{"counter":1,"zone":""}
Concepts
In Kuma we define two concepts around identity that need to be well understood:
- Identity - Who a workload is - A workload’s identity is the name encoded in its certificate, and this identity is considered valid only if the certificate is signed by a Trust.
- Trust - Who to believe - Trust defines which identities you accept as valid, and is established through trusted certificate authorities (CA) that issue those identities. Trust is attached to trust domain, and there can be multiple Trusts in the cluster.
Issuing Identity
In Kuma we have MeshIdentity
resource responsible for managing identity. To issue new identity in Mesh,
we need to create resource:
echo "apiVersion: kuma.io/v1alpha1
kind: MeshIdentity
metadata:
name: identity
namespace: kuma-system
labels:
kuma.io/mesh: default
spec:
selector:
dataplane:
matchLabels: {}
spiffeID:
trustDomain: '{{ .Mesh }}.{{ .Zone }}.mesh.local'
path: '/ns/{{ .Namespace }}/sa/{{ .ServiceAccount }}'
provider:
type: Bundled
bundled:
meshTrustCreation: Enabled
insecureAllowSelfSigned: true
certificateParameters:
expiry: 24h
autogenerate:
enabled: true" | kubectl apply -f -
Let’s take a closer look at resource we’ve just applied. MeshIdentity
uses selector
field to select data planes for
which identity should be issued. In our example, identity will be issued for all data planes in Mesh.
Next is spiffeID
field. This field contains templates for building spiffeID for our workloads. In this example we will build
trust domain from Mesh name, zone name and .mesh.local
suffix. Path for spiffeID will be built from namespace and service account name.
Example spiffeID will look like this spiffe://default.default.mesh.local/ns/kuma-demo/sa/default
.
Last thing we see in this example is provider
field. This field contains configuration specific to identity provider.
In this guide we will be working with Bundled
provider, but you can also configure Spire provider. This configuration will
enable MeshTrust
generation, allow self-signed certificates, and will set cert expiry time to 24 h.
Inspecting trust configuration
This MeshIdentity
will create MeshTrust
resource for us. We can check if it was created by running:
kubectl get meshtrusts -n kuma-system
You should get a similar response:
NAME AGE
identity 45s
We can now take closer look at the MeshTrust
resource that was generated. We can get full resource by running:
kubectl get meshtrust identity -n kuma-system -oyaml
Generated MeshTrust
resource should look like this:
apiVersion: kuma.io/v1alpha1
kind: MeshTrust
metadata:
labels:
kuma.io/env: kubernetes
kuma.io/mesh: default
kuma.io/origin: zone
kuma.io/zone: default
name: identity
namespace: kuma-system
spec:
caBundles:
- pem:
value: |
-----BEGIN CERTIFICATE-----
MIIDgzCCAmugAwIBAgIRAO8psy2B4YbbzSvhSaRYTlMwDQYJKoZIhvcNAQELBQAw
QzENMAsGA1UEChMES3VtYTENMAsGA1UECxMETWVzaDEjMCEGA1UEAxMaZGVmYXVs
dC5kZWZhdWx0Lm1lc2gubG9jYWwwHhcNMjUwOTAyMTMxMjA4WhcNMzUwODMxMTMx
MjE4WjBDMQ0wCwYDVQQKEwRLdW1hMQ0wCwYDVQQLEwRNZXNoMSMwIQYDVQQDExpk
ZWZhdWx0LmRlZmF1bHQubWVzaC5sb2NhbDCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBAOERv23rg9mmNdNu2pULOMD5/5IwW7SW9WFdfEYtpuM8OxnpLOZl
HQo7ZnPhPbpvqNYz8wpgZmOD3zMu4PT2W+Rdv/qC4wSbY1kCrFxbcc88sjmRFVJm
1fQFgzcu91IZn4cWo7XpNA7a1t46kzAiM5oz6WsLcZ76AhG/A82L60z/k1wvFqMK
aORPysIMLLEBs1A09iuzqvlp+7iv8BiAVgu3KD1RX5mSOyg91U/g1XhzOrHV1WY5
VoSs9l6mbJDeVdlaLC5wQzD4E71XWpqnHXxjG695vhxMZLqHIuyxt4WXKEF78ma/
1V5k/Sc7nUHmFBT1a0B6XCDvzdqGJYa58+sCAwEAAaNyMHAwDgYDVR0PAQH/BAQD
AgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFIrDUs8m5iAB+f9Jx4gFC7e4
hKlBMC4GA1UdEQQnMCWGI3NwaWZmZTovL2RlZmF1bHQuZGVmYXVsdC5tZXNoLmxv
Y2FsMA0GCSqGSIb3DQEBCwUAA4IBAQDZvq4Pz7VxscfP+DkqNJDMKMidbaEnPbac
nr5RG2YJ4+HuGakvHLc7Of8a3FSYAQX2cgjRrGLAnsC7zrOxYT3kEuXZzbQ545rw
eZp9I6AdTa5fd0G9vnmUDkJnpQNDg0Ao/vJfv0hSmouJrkp9yvuR0VkLrMSkRUN+
rHdPHVlnEBDRsZv8a1/ShVffF5mmdX5qifw35Iv+owS+ATWfhOO3nvOMKR4tY9qb
aZ/Vckmai7QO4BhGUiVnhUdPQCWqQoxE3h8+kMD9BL1Vxpi8uXpLmQpi8HQbaBKO
lahgDp2cp52Edw5luev1Vx/y23R5F6gxyO1h1lX7mb5qV8PoK0WE
-----END CERTIFICATE-----
type: Pem
origin:
kri: kri_mid_default_default_kuma-system_identity_
trustDomain: default.default.mesh.local
In the generated MeshTrust
we can see caBundle
that was generated by the control plane and trust domain created based on
template from MeshIdentity
resource. We also have generated trustDomain
, and origin
which specifies KRI (Kuma Resource Identifier)
of MeshIdentity
used to generate this trust.
MeshIdentity in GUI
In the GUI when you open Mesh view, you will see new sections with MeshIdentity
and MeshTrust
, where you can inspect these resources.

Testing connectivity with MeshIdentity
We can now make some requests to our demo-app:
curl -XPOST localhost:5050/api/counter
We should see errors like this:
{"instance":"d11ee97a4b45ff3a7b59091d1612b7f7","status":500,"title":"failed to retrieve zone","type":"https://github.com/kumahq/kuma-counter-demo/blob/main/ERRORS.md#INTERNAL-ERROR"}
Since we issued identity for our workloads, mTLS was also configured. Zero trust is default behavior in this situation, and because
we don’t have any MeshTrafficPermission
configured we see these errors.
Allowing traffic in kuma-demo namespace
To allow traffic in kuma-demo
we need to create MeshTrafficPermission
. Apply this:
echo "apiVersion: kuma.io/v1alpha1
kind: MeshTrafficPermission
metadata:
name: mtp
namespace: kuma-demo
labels:
kuma.io/mesh: default
spec:
rules:
- default:
allow:
- spiffeID:
type: Prefix
value: spiffe://default.default.mesh.local/ns/kuma-demo" | kubectl apply -f -
This MeshTrafficPermission
uses rules API with spiffeID matching. This policy will allow all traffic from workloads which spiffeID starts with:
spiffe://default.default.mesh.local/ns/kuma-demo
. This spiffeID is based on template from MeshIdentity
we’ve created earlier, every workload in default
Mesh.
and in kuma-demo
namespace will have spiffeID with this prefix. In the future if you want to be more specific you can
allow only workloads matching its exact
spiffeID.
We can now try if traffic works. Run:
curl -XPOST localhost:5050/api/counter
You should see something similar to:
{"counter":3,"zone":""}
What you’ve learned
We’ve learned how to issue identity with MeshIdentity
. Also, we’ve seen how MeshTrust
is generated based on MeshIdentity
.
On top of that, we’ve seen how to allow traffic using MeshTrafficPermission
with spiffeID matchers.
Next steps
- Checkout MeshIdentity guide with Spire provider
- Read more about MeshIdentity and MeshTrust
- Explore MeshTrafficPermission with spiffeID matchers