Secretless Workload Identity on K8s

Deploy SPIRE on Kubernetes to issue cryptographic identities with zero static secrets.

Introduction

30 Second Summary

Every time two pieces of software need to communicate securely, someone creates a password or API key and stores it somewhere. What if your software could prove its identity automatically, like a fingerprint, with no shared secrets involved?

In this project, you will use the SPIFFE identity framework and its runtime, SPIRE, to issue cryptographic identities to workloads running on a local Kubernetes cluster. No passwords, no API keys, no static secrets.

What You'll Build

A local Kubernetes environment running the full SPIRE identity infrastructure, where workloads receive short-lived X.509 certificates based on what they are, not who they say they are.

By the end of this project, you'll have:

  • A minikube cluster configured for SPIRE's PSAT attestation.
  • A SPIRE Server deployed as the root of trust and a SPIRE Agent deployed as the per-node identity broker.
  • Workload registration entries that map Kubernetes selectors to SPIFFE IDs, with a test workload that fetches its own X.509-SVID from the Workload API.
  • Secret Mission: Build an SVID Inspector web app that visually compares the cryptographic identities of two workloads side by side.

Are there any prerequisites?

This project assumes basic familiarity with Kubernetes concepts like pods, deployments, namespaces, and service accounts. You should also have Homebrew installed on macOS.

Before We Start

Before We Start...

Set Up Your Local Kubernetes Environment

Before you can deploy any identity infrastructure, you need a Kubernetes cluster running locally on your machine.

In this step, you will install three tools: Docker Desktop (the container runtime), minikube (a local Kubernetes cluster), and kubectl (the Kubernetes command-line tool). Then you will start a cluster with special configuration flags that SPIRE needs and clone the tutorial files.

In this step, get ready to:
  • Install Docker Desktop, minikube, and kubectl.
  • Start a minikube cluster with SPIRE PSAT attestation flags.
  • Clone the spire-tutorials repository and locate the quickstart YAML files.
Install Docker Desktop, minikube, and kubectl

Each of these three tools plays a different role. Docker Desktop runs containers. Minikube creates a single-node Kubernetes cluster inside a Docker container. Kubectl lets you talk to that cluster from your terminal.

Since all three install through Homebrew, the process is straightforward.

  • Press Cmd+Space to open Spotlight Search.
  • Type Terminal and press Enter to open it.
  • Install Docker Desktop by running this command:
brew install --cask docker-desktop

What does this command do?

The --cask flag tells Homebrew to install a graphical macOS application (Docker Desktop) instead of a command-line-only tool.

  • Once the installation finishes, open Docker Desktop by pressing Cmd+Space, typing Docker, and pressing Enter.
  • Accept any permissions prompts that appear. Docker Desktop needs system access to manage containers.
  • Wait for Docker Desktop to fully start. You will see the Docker whale icon in your menu bar at the top of your screen.

Why do I need to open Docker Desktop?

Docker Desktop must be running before you can start minikube. Minikube uses Docker as its container runtime to create and manage the Kubernetes cluster.

  • Verify Docker is running by running this command:
docker --version

✔️ I see a version number

Docker is running and ready. Move on to the next install.

⨯ Command not found or Docker not running

  • Make sure Docker Desktop is fully open. Look for the whale icon in your menu bar.
  • If the icon is not there, open Docker Desktop again by pressing Cmd+Space, typing Docker, and pressing Enter.
  • Wait a minute for Docker Desktop to finish starting, then run docker --version again.
  • Install minikube by running this command:
brew install minikube
  • Verify minikube is installed by running:
minikube version

✔️ I see a version number

Minikube is installed and ready. Move on to the next install.

⨯ Command not found

  • Run brew install minikube again and check for any error messages in the output.
  • If Homebrew itself is not found, reinstall it by following the instructions at brew.sh.
  • Install kubectl by running this command:
brew install kubernetes-cli
  • Verify kubectl is installed by running:
kubectl version --client

✔️ I see a version number

Kubectl is installed and ready. All three tools are good to go.

⨯ Command not found

  • Run brew install kubernetes-cli again and check for any error messages in the output.
  • Close your terminal and open a new one, then run kubectl version --client again.
Start minikube with the SPIRE PSAT attestation flags

SPIRE uses a method called PSAT (Projected Service Account Token) attestation to verify the identity of Kubernetes nodes. This requires the Kubernetes API server to be configured with specific signing keys and audience settings.

Minikube lets you pass these configuration flags at startup. The command is long because it includes five --extra-config flags that tell the API server how to handle service account tokens.

  • Start your minikube cluster with the SPIRE-specific flags by running this command:
minikube start \
  --driver=docker \
  --extra-config=apiserver.service-account-signing-key-file=/var/lib/minikube/certs/sa.key \
  --extra-config=apiserver.service-account-key-file=/var/lib/minikube/certs/sa.pub \
  --extra-config=apiserver.service-account-issuer=api \
  --extra-config=apiserver.api-audiences=api,spire-server \
  --extra-config=apiserver.authorization-mode=Node,RBAC

What do these flags do?

  • service-account-signing-key-file and service-account-key-file point the API server to the keys it uses to sign and verify service account tokens.
  • service-account-issuer sets the issuer claim in projected tokens, which SPIRE checks during node attestation.
  • api-audiences defines which audiences the API server accepts. SPIRE Server is included here so it can validate tokens from nodes.
  • authorization-mode enables Node authorization and RBAC. Both are required for SPIRE's role-based access.

Why PSAT instead of SAT?

SPIRE originally supported SAT (Service Account Token) attestation. SAT-based node attestation is deprecated as of SPIRE 1.12.0. PSAT uses projected service account tokens, which are audience-bound and time-limited. This makes them more secure and is the recommended approach for all new SPIRE deployments.

This command takes a minute or two to complete. Minikube downloads a Kubernetes image, creates a container, and starts the cluster inside it.

  • Verify the cluster is running by running:
minikube status
  • You should see host: Running, kubelet: Running, and apiserver: Running in the output.
  • Confirm that kubectl is connected to the cluster by running:
kubectl get nodes
  • You should see the minikube node listed with a status of Ready.

Cluster not starting?

  • Make sure Docker Desktop is running. The Docker whale icon should be visible in your menu bar.
  • If minikube fails with a driver error, confirm Docker is accessible by running docker ps. If that command fails, restart Docker Desktop and wait for it to fully start.
  • Help me troubleshoot my minikube cluster startup. I'm running on macOS Apple Silicon with Docker Desktop as the driver.
Clone the spire-tutorials repository

The SPIRE project provides a repository of tutorial YAML files that define each component you will deploy. Instead of writing these manifests by hand, you will clone them and use the pre-built quickstart files.

  • Move to your Desktop by running this command:
cd ~/Desktop
  • Clone the spire-tutorials repository by running:
git clone https://github.com/spiffe/spire-tutorials.git

First time using Git on this Mac?

macOS does not include Git out of the box. When you run a git command for the first time, macOS prompts you to install the Xcode Command Line Tools. Click Install and wait for the download to finish, then run the git clone command again.

  • Navigate into the quickstart directory by running:
cd spire-tutorials/k8s/quickstart
  • Confirm the YAML files are present by running:
ls
  • You should see several .yaml files in the output, including server-statefulset.yaml, agent-daemonset.yaml, and client-deployment.yaml. These are the manifests you will use in the next steps to deploy the SPIRE infrastructure.

Don't see any YAML files?

  • Double-check you are in the spire-tutorials/k8s/quickstart directory. Run pwd to see your current path.
  • If the git clone step failed, check your internet connection and try cloning again.
  • Help me find the SPIRE quickstart YAML files. I cloned the spire-tutorials repository but I don't see the expected files.

Your local Kubernetes environment is ready. Next up, you will deploy the SPIRE Server as the root of trust for your cluster.

Deploy the SPIRE Server

Your Kubernetes cluster is running and your quickstart files are ready. Now it's time to deploy the central piece of the SPIFFE identity system.

The SPIRE Server acts as the root of trust for your entire identity infrastructure. It stores workload registration entries, manages the trust bundle, and signs the short-lived X.509 certificates that workloads use to prove their identity.

In this step, get ready to:
  • Create the spire namespace and deploy the server's foundation resources.
  • Deploy the SPIRE Server StatefulSet and verify it reaches Running status.
  • Inspect the server configuration to understand the trust domain and attestor plugins.
Create the spire namespace and deploy foundation resources

Before deploying any SPIRE components, you need a dedicated Kubernetes namespace to keep them organized and isolated from other workloads.

  • Create the spire namespace by running this command:
kubectl apply -f spire-namespace.yaml
  • Verify the namespace was created by running:
kubectl get namespaces

You should see spire in the list of namespaces.

The SPIRE Server needs a service account to run under, a ConfigMap to store the trust bundle, and RBAC permissions to manage that bundle.

  • Deploy the server's service account, trust bundle ConfigMap, and ClusterRole by running:
kubectl apply -f server-account.yaml -f spire-bundle-configmap.yaml -f server-cluster-role.yaml

What do these three resources do?

  • server-account.yaml creates a Kubernetes service account that the SPIRE Server pod runs as. This gives the server an identity within the cluster.
  • spire-bundle-configmap.yaml creates a ConfigMap that holds the trust bundle. The server periodically writes its signing certificates here so agents can verify the server's identity.
  • server-cluster-role.yaml creates a ClusterRole and ClusterRoleBinding that allow the server to read and update the trust bundle ConfigMap.
  • Confirm the resources were created by running:
kubectl get serviceaccount --namespace spire

You should see spire-server listed alongside the default service account.

Seeing a "not found" or namespace error?

Make sure you ran the namespace creation command first. The resources in this command are deployed into the spire namespace, which must exist before they can be created.

Also confirm your terminal is still in the spire-tutorials/k8s/quickstart directory. The kubectl apply -f commands reference YAML files by relative path.

Help me troubleshoot my SPIRE Server foundation resource deployment

Deploy the server ConfigMap, StatefulSet, and Service

The foundation resources are in place. Now you can deploy the server itself, which includes its configuration file, the StatefulSet that runs the server pod, and the Service that exposes it within the cluster.

  • Deploy the SPIRE Server by running:
kubectl apply -f server-configmap.yaml -f server-statefulset.yaml -f server-service.yaml

What do these three resources do?

  • server-configmap.yaml contains server.conf, the main configuration file for the SPIRE Server. It defines the trust domain, attestor plugins, and data storage settings.
  • server-statefulset.yaml creates a StatefulSet that runs the SPIRE Server as a single pod (spire-server-0). A StatefulSet is used instead of a Deployment because the server needs a stable network identity and persistent storage.
  • server-service.yaml creates a Kubernetes Service that lets agents connect to the server on port 8081.

The server pod may take a moment to pull its container image and start up.

  • Check the StatefulSet status by running:
kubectl get statefulset --namespace spire

You should see spire-server with 1/1 under the READY column.

  • Confirm the pod is running by running:
kubectl get pods --namespace spire

You should see spire-server-0 with status Running and 1/1 READY.

  • Verify the service is exposed by running:
kubectl get services --namespace spire

You should see the spire-server service listed.

Pod not reaching Running status?

If the pod shows ContainerCreating, the container image is still being pulled. Wait 30 seconds and run the kubectl get pods command again.

If the pod is in CrashLoopBackOff, check the logs for details by running:

kubectl logs spire-server-0 --namespace spire

If the pod is stuck in Pending, make sure your minikube cluster started successfully and has enough resources.

Help me debug my SPIRE Server pod status

Inspect the server configuration

The SPIRE Server is running, but it's worth understanding how it's configured. The server's behavior is defined in server.conf, which is embedded inside the server-configmap.yaml file.

  • View the server configuration by running:
cat server-configmap.yaml

Scroll through the output and look for three key configuration sections.

What are the three key parts of this configuration?

trust_domain is set to example.org. This is the root namespace for all SPIFFE IDs issued by this server. Every workload identity starts with spiffe://example.org/.

The NodeAttestor plugin is set to k8s_psat. This means the server verifies nodes using Projected Service Account Tokens. Those are the API server flags you configured in the previous step.

The NodeResolver or workload attestor uses k8s. This lets the server identify workloads based on Kubernetes metadata like namespaces and service accounts.

What is a trust domain?

A trust domain is the boundary of trust in SPIFFE. All workloads within the same trust domain share a common root of trust, meaning they can verify each other's certificates. The domain name example.org is used here for learning purposes.

In production, your trust domain would be a domain you control, like prod.yourcompany.com.

Your SPIRE Server is deployed and running as the root of trust for your cluster. Next up, you'll deploy the SPIRE Agent, the per-node identity broker that connects workloads to the server.

Deploy the SPIRE Agent

Your SPIRE Server is running as the root of trust for your cluster. The next component to deploy is the SPIRE Agent, which is the per-node identity broker that actually hands out identities to workloads.

The Agent runs as a DaemonSet, meaning Kubernetes places one Agent pod on every node in your cluster. It connects to the Server to establish trust, then exposes a local socket that workloads use to request their cryptographic identity.

In this step, get ready to:
  • Create the Agent's service account and RBAC permissions.
  • Deploy the Agent ConfigMap and DaemonSet.
  • Understand how the Workload API socket connects agents to workloads.
Create the Agent service account and RBAC permissions

The Agent needs its own identity in the cluster and permission to query the Kubernetes API. It uses this access to look up information about pods and nodes when verifying workload identities.

  • Deploy the Agent's service account and cluster role by running this command:
kubectl apply -f agent-account.yaml -f agent-cluster-role.yaml

What does this command do?

This applies two YAML files that set up the Agent's identity and permissions in your cluster.

  • agent-account.yaml creates a ServiceAccount called spire-agent in the spire namespace.
  • agent-cluster-role.yaml creates a ClusterRole and ClusterRoleBinding that grant the Agent access to query the kubelet API for node and pod information. The Agent needs this to verify (attest) the identity of workloads requesting certificates.
  • You should see output confirming each resource was created, including the service account, cluster role, and cluster role binding.

Seeing an error?

  • Make sure you are still in the spire-tutorials/k8s/quickstart directory. The YAML files must be in your current directory for kubectl apply -f to find them.
  • Confirm the spire namespace still exists by running kubectl get namespace spire.
  • help me troubleshoot this RBAC deployment error
Deploy the Agent ConfigMap and DaemonSet

With the Agent's permissions in place, you can now deploy its configuration and the DaemonSet that runs it on every node.

  • Deploy the Agent's configuration and DaemonSet by running this command:
kubectl apply -f agent-configmap.yaml -f agent-daemonset.yaml

What does this command do?

This applies two more YAML files that configure and launch the Agent.

  • agent-configmap.yaml contains the agent.conf file. This tells the Agent which trust domain to use (example.org), where to find the SPIRE Server, and which attestation plugins to run.
  • agent-daemonset.yaml creates a DaemonSet that runs one Agent pod on every node. It also includes an init container that waits for the SPIRE Server to be reachable before starting the Agent.
  • Verify the Agent DaemonSet is running by running these commands:
kubectl get daemonset --namespace spire
kubectl get pods --namespace spire

The first command should show spire-agent with 1 under the DESIRED column and 1 under the READY column.

The second command should show both spire-server-0 and a spire-agent pod, each with status Running.

Agent pod shows ContainerCreating?

The Agent pod may take 30-60 seconds to reach Running status. The init container needs to confirm the SPIRE Server is reachable before the Agent starts. Wait a moment and re-run the commands.

Agent pod not reaching Running status?

  • Check that your SPIRE Server is still running by running kubectl get pods --namespace spire. If spire-server-0 is not Running, the Agent cannot start.
  • View the Agent logs for specific errors by running kubectl logs -n spire -l app=spire-agent.
  • If the pod is stuck in ImagePullBackOff, your Docker Desktop may have lost connectivity. Restart Docker Desktop and try again.
  • help me debug why my SPIRE Agent pod is not starting
Examine the Workload API socket

The Agent is running, but how do workloads actually talk to it? The answer is a Unix domain socket that the Agent exposes on the node's filesystem.

  • Inspect the Agent DaemonSet YAML to see how the socket is configured by running:
cat agent-daemonset.yaml

Look at the volumes section near the bottom. You should see a volume named spire-agent-socket with a hostPath pointing to /run/spire/sockets.

How does the Workload API socket work?

The Agent creates a Unix domain socket file at /run/spire/sockets/agent.sock on the node. Because this path is a hostPath volume, it lives on the node's filesystem rather than inside the Agent container.

Any workload pod on the same node can mount this same /run/spire/sockets path and connect to the socket. This is how workloads request their identity from the Agent without needing any passwords or API keys.

This is the Workload API. In the next step, you will deploy a workload that mounts this socket and fetches its cryptographic identity through it.

Why a DaemonSet instead of a Deployment?

A Deployment might schedule all replicas on a single node, leaving other nodes without an Agent. A DaemonSet guarantees exactly one Agent pod on every node, so every workload on every node has access to the Workload API socket.

Your SPIRE infrastructure is now complete. The Server holds the root of trust, and the Agent on each node is ready to broker identities. Next, you will register workloads and fetch your first secretless identity.

Register Workloads and Fetch a Secretless Identity

Your SPIRE infrastructure is in place. The server holds the root of trust for the example.org trust domain, and the agent is running on the node, ready to broker identities to workloads.

The missing piece is telling the server which workloads should receive identities. Right now, the server has no registration entries, so it will not issue certificates to anyone. You will fix that by creating entries that map Kubernetes selectors to SPIFFE IDs, then deploy a test workload that fetches its own cryptographic identity.

In this step, get ready to:
  • Create registration entries for the SPIRE Agent node and a test workload.
  • Deploy a test client pod that connects to the Workload API.
  • Fetch an X.509-SVID to prove the workload received a secretless identity.
Create the node and workload registration entries

A registration entry is a rule stored in the SPIRE Server. It says "when a workload matches these selectors, issue it this SPIFFE ID." You need two entries: one for the agent node itself, and one for the test workload.

  • Create the node registration entry for the SPIRE Agent by running this command:
kubectl exec -n spire spire-server-0 -- /opt/spire/bin/spire-server entry create -spiffeID spiffe://example.org/ns/spire/sa/spire-agent -selector k8s_psat:cluster:demo-cluster -selector k8s_psat:agent_ns:spire -selector k8s_psat:agent_sa:spire-agent -node

What does this command do?

This command runs inside the spire-server-0 pod and creates a node registration entry. The -node flag tells SPIRE this entry describes a node (the agent), not a workload.

The three k8s_psat selectors tell the server how to identify this agent: it must be in the demo-cluster cluster, in the spire namespace, and running under the spire-agent service account. Only an agent matching all three selectors will be trusted.

You should see output that starts with Entry ID followed by a unique identifier, confirming the entry was created.

  • Create the workload registration entry for the test client by running this command:
kubectl exec -n spire spire-server-0 -- /opt/spire/bin/spire-server entry create -spiffeID spiffe://example.org/ns/default/sa/default -parentID spiffe://example.org/ns/spire/sa/spire-agent -selector k8s:ns:default -selector k8s:sa:default

What does this command do?

This creates a workload registration entry. It maps any pod in the default namespace running under the default service account to the SPIFFE ID spiffe://example.org/ns/default/sa/default.

The -parentID links this workload entry to the node entry you just created. The agent (parent) is responsible for attesting workloads on its node and passing their identity requests up to the server.

You should see another Entry ID in the output, confirming the workload entry was created.

Not seeing an Entry ID?

  • Make sure spire-server-0 is still in Running status. Run kubectl get pods -n spire to check.
  • Check for typos in the command, especially in the SPIFFE ID paths and selector values. The selectors are case-sensitive.
  • If you see a message about a similar entry already existing, the entry was created successfully on a previous attempt. You can continue to the next substep.

Help me troubleshoot the SPIRE registration entries

Deploy the test client workload

With the registration entries in place, you can deploy a workload that will request its identity from the Workload API. The test client pod mounts the agent's Unix domain socket so it can communicate with the agent directly.

  • Deploy the test client workload by running this command:
kubectl apply -f client-deployment.yaml
  • Wait a few seconds for the pod to start, then verify it is running:
kubectl get pods

You should see a client pod with Running status in the default namespace.

Why does the client mount a hostPath volume?

The client-deployment.yaml file mounts /run/spire/sockets from the host into the pod. This is the directory where the SPIRE Agent exposes its Unix domain socket (agent.sock).

By sharing this socket, the client pod can call the Workload API without any network configuration or shared secrets.

Client pod not reaching Running status?

  • Run kubectl describe pod followed by the pod name to see detailed event messages.
  • If you see image pull errors, check that Docker Desktop is running and has internet access.
  • Make sure the SPIRE Agent pod is still running. The client depends on the agent socket being available on the node.

Help me debug my client pod startup

Fetch your workload's X.509-SVID

This is the moment where everything comes together. You will exec into the client pod and ask the Workload API for the pod's identity. No password, no API key, no shared secret is involved.

  • Fetch the X.509-SVID from the Workload API by running this command:
kubectl exec -it $(kubectl get pods -o=jsonpath='{.items[0].metadata.name}' -l app=client) -- /opt/spire/bin/spire-agent api fetch -socketPath /run/spire/sockets/agent.sock

What does this command do?

The outer kubectl exec opens a session inside the client pod. The inner $(kubectl get pods ... -l app=client) automatically finds the client pod's name so you do not have to look it up manually.

Inside the pod, /opt/spire/bin/spire-agent api fetch calls the Workload API through the Unix domain socket at /run/spire/sockets/agent.sock. The agent verifies the calling process against the registration entries you created, then returns the matching X.509-SVID.

  • Look for the SPIFFE ID line in the output. It should show spiffe://example.org/ns/default/sa/default.
  • Check the SVID Valid After and SVID Valid Until timestamps. The gap between them is approximately 1 hour, which is the default SVID TTL.

Why is this a big deal?

Look at the client pod's deployment YAML. There is no env section with API keys. There is no Secret volume mount. There is no .env file.

The SPIRE Agent checked the pod's Kubernetes metadata (namespace and service account) against the registration entry you created. Because everything matched, the server signed and issued a fresh certificate. This is secretless identity.

Seeing a permission denied or empty response?

  • The most common cause is a mismatch between the registration entry selectors and the pod's actual Kubernetes metadata. Double-check that the client pod is in the default namespace and uses the default service account.
  • Make sure both registration entries (node and workload) were created successfully. You can list all entries by running the following command inside the server pod.
kubectl exec -n spire spire-server-0 -- /opt/spire/bin/spire-server entry show
  • If the agent pod restarted since you created the entries, the agent needs a few seconds to re-attest with the server. Wait 10-15 seconds and try the fetch command again.

Help me debug the SVID fetch

Secret mission

Build an SVID Inspector

You've proven that SPIRE issues cryptographic identities to workloads. Now, can you build a real web application that reads those identities and displays them visually? Deploy two instances with different SPIFFE IDs and compare them side by side to prove identity isolation.

Clean Up Your Resources

Clean Up Your Resources

This project runs entirely on your local machine, so there are no ongoing cloud costs. Decide whether to keep your resources running, pause them to come back later, or delete them entirely.

Resources you used:

  • A minikube cluster with SPIRE Server, Agent, and workload pods (consuming CPU, memory, and disk while running).
  • Cluster-level RBAC roles and bindings (spire-server-trust-role, spire-agent-cluster-role).
  • The cloned spire-tutorials repository and Secret Mission files on your Desktop.
  • Docker Desktop, minikube, and kubectl installed via Homebrew.

Keep everything running

No action needed. Choose this if you are still actively building or experimenting with SPIRE.

Docker Desktop and the minikube VM will continue using CPU, memory, and disk while running. Your SPIRE Server, Agent, and all registered workloads will stay active.

Pause - I'll come back to this later

Shut down the minikube VM to free up local resources while keeping your cluster configuration intact.

  • Stop the minikube cluster by running:
minikube stop
  • When you are ready to resume, start the cluster again by running:
minikube start

You do not need to pass the SPIRE API server flags again on restart. Minikube detects your existing profile and resumes the cluster with its previous configuration.

Delete - I don't want to use this again

Remove all project resources and start fresh. This deletes the Kubernetes cluster, all SPIRE components, and the local files.

  • Delete all workload deployments in the default namespace by running:
kubectl delete deployment client svid-viewer-a svid-viewer-b
  • Delete the spire namespace, which removes the SPIRE Server and Agent pods:
kubectl delete namespace spire
  • Delete the cluster-level RBAC roles and bindings by running:
kubectl delete clusterrole spire-server-trust-role spire-agent-cluster-role
kubectl delete clusterrolebinding spire-server-trust-role-binding spire-agent-cluster-role-binding
  • Delete the minikube cluster entirely by running:
minikube delete
  • Remove the cloned repository and all local project files from your Desktop by running:
rm -rf ~/Desktop/spire-tutorials
  • If you no longer need minikube and kubectl, uninstall them via Homebrew by running:
brew uninstall minikube
brew uninstall kubectl
  • To uninstall Docker Desktop, open the Docker Desktop dashboard, click the Troubleshoot icon (top right), then select Uninstall.

That's a Wrap!

That's a Wrap!

Nice work! You just deployed a full SPIRE identity infrastructure on Kubernetes and proved that workloads can receive cryptographic identities with zero static secrets.

You've learned how to:

  • Deploy a SPIRE Server and SPIRE Agent on a local Kubernetes cluster configured with PSAT attestation, establishing a root of trust for the example.org trust domain.
  • Create registration entries that map Kubernetes selectors like namespace and service account to SPIFFE IDs, defining which workloads receive which cryptographic identities.
  • Fetch an X.509-SVID from the Workload API, proving a workload received a short-lived certificate through attestation alone.
  • Secret Mission: Built an SVID Inspector web app that visually compared two workloads' cryptographic identities, proving SPIRE issues unique, isolated X.509 certificates to each workload based on attestation.

Ready to quiz yourself?