<p>I want to run a pod that listens for updates to endpoint lists (I'm not yet ready to adopt the alpha-level feature of endpoint sets, but I'll expand to that eventually.)</p>
<p>I have this code:</p>
<pre><code>package main

import (
    &quot;fmt&quot;
    &quot;os&quot;
    &quot;os/signal&quot;
    &quot;sync&quot;
    &quot;syscall&quot;

    &quot;k8s.io/apimachinery/pkg/util/runtime&quot;
    &quot;k8s.io/client-go/informers&quot;
    &quot;k8s.io/client-go/kubernetes&quot;
    &quot;k8s.io/client-go/rest&quot;
    &quot;k8s.io/client-go/tools/cache&quot;
)

func ReadKubeConfig() (*rest.Config, *kubernetes.Clientset, error) {
    config, err := rest.InClusterConfig()
    if err != nil {
            return nil, nil, err
    }
    clients, err := kubernetes.NewForConfig(config)
    if err != nil {
            return nil, nil, err
    }
    return config, clients, nil
}

func main() {
    _, cs, err := ReadKubeConfig()
    if err != nil {
            fmt.Printf(&quot;could not create Clientset: %s\n&quot;, err)
            os.Exit(1)
    }
    factory := informers.NewSharedInformerFactory(cs, 0)
    ifmr := factory.Core().V1().Endpoints().Informer()
    stop := make(chan struct{})
    ifmr.AddEventHandler(cache.ResourceEventHandlerFuncs{
            AddFunc: func(next interface{}) {
                    fmt.Printf(&quot;AddFunc(%v)\n&quot;, next)
            },
            UpdateFunc: func(prev, next interface{}) {
                    fmt.Printf(&quot;UpdateFunc(%v, %v)\n&quot;, prev, next)
            },
            DeleteFunc: func(prev interface{}) {
                    fmt.Printf(&quot;DeleteFunc(%v)\n&quot;, prev)
            },
    })
    wg := &amp;sync.WaitGroup{}
    wg.Add(1)
    go func() {
            defer runtime.HandleCrash()
            ifmr.Run(stop)
            wg.Done()
    }()
    ch := make(chan os.Signal, 1)
    signal.Notify(ch, os.Interrupt)
    signal.Notify(ch, os.Signal(syscall.SIGTERM))
    signal.Notify(ch, os.Signal(syscall.SIGHUP))
    sig := &lt;-ch
    fmt.Printf(&quot;Received signal %s\n&quot;, sig)
    close(stop)
    wg.Wait()
}
</code></pre>
<p>I get this error when deploying and running:</p>
<pre><code>kubeendpointwatcher.go:55: Failed to list *v1.Endpoints: endpoints is forbidden: User &quot;system:serviceaccount:eng:default&quot; cannot list resource &quot;endpoints&quot; in API group &quot;&quot; at the cluster scope
</code></pre>
<p>I have the following role and role binding defined and deployed to the &quot;eng&quot; namespace:</p>
<pre><code>watch_endpoints$ kubectl -n eng get role mesh-endpoint-read -o yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  creationTimestamp: &quot;2021-07-08T19:59:20Z&quot;
  name: mesh-endpoint-read
  namespace: eng
  resourceVersion: &quot;182975428&quot;
  selfLink: /apis/rbac.authorization.k8s.io/v1/namespaces/eng/roles/mesh-endpoint-read
  uid: fcadcc2a-19d0-4d6e-bee1-78413f51b91b
rules:
- apiGroups:
  - &quot;&quot;
  resources:
  - endpoints
  verbs:
  - get
  - list
  - watch
</code></pre>
<p>I have the following rolebinding:</p>
<pre><code>watch_endpoints$ kubectl -n eng get rolebinding mesh-endpoint-read -o yaml | sed -e 's/^/    /g'

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  creationTimestamp: &quot;2021-07-08T19:59:20Z&quot;
  name: mesh-endpoint-read
  namespace: eng
  resourceVersion: &quot;182977845&quot;
  selfLink: /apis/rbac.authorization.k8s.io/v1/namespaces/eng/rolebindings/mesh-endpoint-read
  uid: 705a3e50-2a73-47ed-aa62-0ea48f3493ee
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: mesh-endpoint-read
subjects:
- kind: ServiceAccount
  name: default
  namespace: default
</code></pre>
<p>You will note that I apply it to both the <code>default</code> namespace and the <code>eng</code> namespace serviceaccount named <code>default</code> although the error message seems to indicate that it is indeed running in the <code>default</code> serviceaccount in the <code>eng</code> namespace.</p>
<p>I have previously used Role and RoleBinding and ServiceAccount objects that work as expected, so I don't understand why this doesn't work. What am I missing?</p>
<p>For testing/reproduction purposes, I run this program by doing <code>kubectl cp</code> of a built binary (cgo off) into a container created with <code>kubectl -n eng create deplpoy</code> with a vanilla <code>ubuntu</code> image running <code>/bin/sh -c sleep 999999999</code>, and then executing a /bin/bash shell in that pod-container.</p>

Jon Watte
<p>You have created <code>role</code> and <code>rolebinding</code> for <code>eng</code> namespace. However, as per the error message:</p>
<pre><code>kubeendpointwatcher.go:55: Failed to list *v1.Endpoints: endpoints is forbidden: User &quot;system:serviceaccount:eng:default&quot; cannot list resource &quot;endpoints&quot; in API group &quot;&quot; at the cluster scope
</code></pre>
<p>you are doing query for endpoints at the &quot;<code>cluster</code>&quot; scope. Either try to limit your query to eng namespace or use <code>clusterrole</code>/<code>clusterbindings</code></p>
<p>Error message provide hint(<code>system:serviceaccount:eng:default</code>)that <code>serviceaccount</code> running in <code>eng</code> namespace, whose name is <code>default</code> does not have permission to query <code>ep</code> at cluster scope.</p>
<p><strong>To validate this</strong>, you can run two <code>curl</code> calls, first <code>exec</code> into the pod using the same <code>sa</code> and then run the following for <code>eng</code> namespace and later try it on other namespaces.</p>
<pre><code>curl -v --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt -H &quot;Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)&quot; https://kubernetes.default.svc/api/v1/namespaces/default/pods
</code></pre>
