Skip to main content
In this lesson you’ll configure a dedicated ServiceAccount and RBAC rules so an Argo Events Sensor can submit Argo Workflows into a target namespace. This resolves “permission denied” errors when the Sensor attempts to create a Workflow using the cluster default ServiceAccount. Why this matters:
  • Using a scoped ServiceAccount with minimal RBAC permissions is more secure than relying on the default ServiceAccount.
  • It prevents permission errors and enables the Sensor to create Workflows in a separate namespace.
Problem evidence (sensor error when using the default ServiceAccount):
{
  "namespace": "argo-events",
  "sensorName": "webhook-sensor",
  "level": "error",
  "time": "2025-10-25T11:00:39Z",
  "msg": "Create request failed",
  "error": "workflows.argoproj.io is forbidden: User \"system:serviceaccount:argo-events:default\" cannot create resource \"workflows\" in API group \"argoproj.io\" in the namespace \"argo\""
}
This shows the Sensor (running in argo-events) attempted to create a Workflow in the argo namespace using the default ServiceAccount and was forbidden. Planned steps:
  1. Create a ServiceAccount in the Sensor’s namespace (argo-events).
  2. Create a Role and RoleBinding in the target namespace (argo) to allow the ServiceAccount to create/read Workflows.
  3. Update the Sensor to use the new ServiceAccount.
  4. Trigger the Sensor and confirm the Workflow is created.

Resources Overview

Resource TypePurposeExample
ServiceAccountIdentity used by the Sensor when creating Workflowsworkflow-trigger-sa
RoleGrants Workflow permissions in the target namespacesubmit-workflow-role
RoleBindingBinds the ServiceAccount from argo-events to the Role in argotrigger-workflow-binding
Sensor spec fieldInstructs the Sensor which ServiceAccount to usespec.template.serviceAccountName
References:

1. Create the ServiceAccount

First, list existing ServiceAccounts in the argo-events namespace, then create a new one called workflow-trigger-sa:
# List ServiceAccounts in the argo-events namespace
kubectl -n argo-events get sa

# Create the new ServiceAccount
kubectl create sa workflow-trigger-sa -n argo-events

# Verify it was created
kubectl -n argo-events get sa
Expected output after creation:
NAME                 SECRETS   AGE
argo-events-sa       0         40m
default              0         40m
workflow-trigger-sa  0         1s

2. Create Role and RoleBinding for Argo Workflows

Create a Role in the argo namespace that grants the minimum permissions the Sensor needs for Argo Workflows, and a RoleBinding that binds the workflow-trigger-sa ServiceAccount from the argo-events namespace to that Role. Manifest to apply:
# sensor-rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: submit-workflow-role
  namespace: argo
rules:
  - apiGroups: ["argoproj.io"]
    resources: ["workflows"]
    verbs: ["create", "get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: trigger-workflow-binding
  namespace: argo
subjects:
  - kind: ServiceAccount
    name: workflow-trigger-sa
    namespace: argo-events
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: submit-workflow-role
Apply the manifest:
kubectl apply -f https://gist.github.com/sidd-harth/e68c477696c7972fafb52171f5ce5a0f/raw/1e1104271876b953ed1592a8dc6553c80b2f86a9/sensor-rbac.yaml
Expected apply output:
role.rbac.authorization.k8s.io/submit-workflow-role created
rolebinding.rbac.authorization.k8s.io/trigger-workflow-binding created
If you see an error like “unknown command ‘apply’ for ‘kubectl1’”, it likely indicates an alias or PATH issue (for example, k pointing to an unexpected binary). Use the full kubectl binary or fix the alias so k maps to kubectl.

3. Update the Sensor to Use the ServiceAccount

Edit your Sensor manifest to set spec.template.serviceAccountName to the ServiceAccount you created (workflow-trigger-sa). Below is a minimal Sensor snippet showing where to configure this:
apiVersion: argoproj.io/v1alpha1
kind: Sensor
metadata:
  name: webhook
  namespace: argo-events
spec:
  template:
    serviceAccountName: workflow-trigger-sa
  dependencies:
    - name: my-webhook-dep
      eventSourceName: webhook
      eventName: my-webhook
  triggers:
    - template:
        name: hello-workflow-trigger
        argoWorkflow:
          source:
            resource:
              apiVersion: argoproj.io/v1alpha1
              kind: Workflow
              metadata:
                generateName: hello-kodekloud-
                namespace: argo
              spec:
                entrypoint: cowsay
                templates:
                  - name: cowsay
                    container:
                      image: rancher/cowsay
                      command: ["cowsay"]
                      args: ["Hello Kode Kloud from ArgoEvents!!"]
Apply the updated Sensor manifest or edit the resource directly:
kubectl apply -f sensor-updated.yaml -n argo-events
# or edit in place
kubectl edit sensor webhook -n argo-events
After updating, the Sensor will use workflow-trigger-sa when creating Workflows in the argo namespace.

4. Trigger the Sensor and Confirm Workflow Creation

Trigger the webhook event source (example using curl):
curl -d '{"message":"hello"}' -H "Content-Type: application/json" -X POST http://localhost:13000/push
You should receive a success response from the event source (for example, success). Then check logs to confirm the event flow: Example event source logs:
namespace=argo-events, eventSourceName=webhook, eventName=my-webhook, level=info, time=2025-10-25T11:12:45Z, msg="Succeeded to publish an event"
namespace=argo-events, eventSourceName=webhook, eventName=my-webhook, level=info, time=2025-10-25T11:12:59Z, msg="Successfully dispatched the request to the event bus"
Example Sensor logs:
{"level":"info","ts":"2025-10-25T11:12:42.920827Z","msg":"Sensor started.","sensorName":"webhook-sensor"}
{"level":"info","ts":"2025-10-25T11:13:00.188816Z","msg":"Successfully processed trigger 'hello-workflow-trigger'","sensorName":"webhook-sensor","triggerName":"hello-workflow-trigger","triggerType":"ArgoWorkflow"}
Verify the Workflow exists in the argo namespace:
kubectl -n argo get wf
Describe the Workflow to inspect labels and the ServiceAccount used by the creator:
kubectl -n argo describe wf <workflow-name>
You should see labels like workflow.argoproj.io/creator and evidence that the Workflow was submitted by the workflow-trigger-sa ServiceAccount. Check the Workflow pod logs to confirm the job ran successfully (example cowsay output):
hello-kodekloud-xxxxx: < Hello Kode Kloud from ArgoEvents!! >
hello-kodekloud-xxxxx: -------------------------------
hello-kodekloud-xxxxx:         \   ^__^
hello-kodekloud-xxxxx:          \  (oo)\_______
hello-kodekloud-xxxxx:             (__)\       )\/\
hello-kodekloud-xxxxx:              ||----w |
hello-kodekloud-xxxxx:              ||     ||

Summary / Event Flow

  • The webhook EventSource receives the HTTP POST and publishes the event to the event bus.
  • The Sensor subscribes to the event bus, evaluates dependencies, and triggers the Argo Workflow.
  • The Sensor uses the configured spec.template.serviceAccountName (workflow-trigger-sa) to submit the Workflow into the argo namespace.
  • The Role and RoleBinding in the argo namespace grant the ServiceAccount the necessary permissions to create and read Argo Workflows.
This setup ensures your Sensor submits Workflows securely using a limited, purpose-built ServiceAccount instead of the cluster default ServiceAccount.

Watch Video

Practice Lab