<p>I accidentally was checking if my pod had the right <code>ServiceAccount</code> and its Bindings. Out of curiosity I wanted to check if the token created from this service account is bound with the certain <code>ClusterRole</code> and <code>ClusterRoleBinding</code> which are read only. I tried few things from <a href="https://kubernetes.io/docs/tasks/access-application-cluster/access-cluster/#without-kubectl-proxy" rel="nofollow noreferrer">Kubernetes Documentation</a>, and I am afraid my understanding is somewhat wrong. Please help me to understand this correctly.</p>
<p>I used existing <code>ClusterRole</code> <code>view</code> and associated to my service account <code>my-sa</code> as <code>ClusterRoleBinding</code>.</p>
<pre><code>APISERVER=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')

SECRET_NAME=$(kubectl get serviceaccount my-sa -o jsonpath='{.secrets[0].name}')

TOKEN=$(kubectl get secret $SECRET_NAME -o jsonpath='{.data.token}' | base64 --decode)
</code></pre>
<p>Then I use the <code>TOKEN</code> to talk to <code>APISERVER</code> for creating a pod in test namespace</p>
<pre><code>curl -X POST $APISERVER/api/v1/namespaces/test/pods\?fieldManager=kubectl-run 
-d '{&quot;kind&quot;:&quot;Pod&quot;,
     &quot;apiVersion&quot;:&quot;v1&quot;,
     &quot;metadata&quot;:
       { &quot;name&quot;:&quot;nginx&quot;,
         &quot;creationTimestamp&quot;:null,
         &quot;labels&quot;:{&quot;run&quot;:&quot;nginx&quot;}
       },
      &quot;spec&quot;: 
          { &quot;containers&quot;:
            [ 
              { &quot;name&quot;:&quot;nginx&quot;,
                &quot;image&quot;:&quot;nginx&quot;,
                &quot;resources&quot;:{}
              } 
            ],
         &quot;restartPolicy&quot;:&quot;Always&quot;,
         &quot;dnsPolicy&quot;:&quot;ClusterFirst&quot;
     },
    &quot;status&quot;:{}
  }' --header &quot;Content-Type: application/json&quot; --header &quot;Authorization: Bearer $TOKEN&quot; --header &quot;Accept: application/json, */*&quot; --insecure
</code></pre>
<p>What Happened</p>
<ol>
<li>This created a successful pod and this token moreoever can create anything.</li>
<li>I even tried to use the <code>default ServiceAccount</code> from the <code>default</code> namespace and the behavior is same</li>
</ol>
<p>My Understanding.</p>
<ol>
<li>This token was associated with the <code>ClusterRole</code> of <code>View</code> hence it should not have allowed the token to create any resource.</li>
<li>Isnt this a loophole because if I am able to get the ServiceAccount Token from a client code and pass it outside the cluster?</li>
</ol>
<p>My Setup: Docker Desktop Kubernetes.</p>
<p>Please help me in understanding what is incorrect in this. I am unable to understand the scope of the <code>ServiceAccount</code> token. I tried to google on this but I couldnt find it. Probably I did not have the right set of words to find it.</p>
<p>EDIT-1:</p>
<p>Describing ClusterRole View.</p>
<pre><code>    Name:         view
Labels:       kubernetes.io/bootstrapping=rbac-defaults
              rbac.authorization.k8s.io/aggregate-to-edit=true
Annotations:  rbac.authorization.kubernetes.io/autoupdate: true
PolicyRule:
  Resources                                    Non-Resource URLs  Resource Names  Verbs
  ---------                                    -----------------  --------------  -----
  bindings                                     []                 []              [get list watch]
  configmaps                                   []                 []              [get list watch]
  endpoints                                    []                 []              [get list watch]
  events                                       []                 []              [get list watch]
  limitranges                                  []                 []              [get list watch]
  namespaces/status                            []                 []              [get list watch]
  namespaces                                   []                 []              [get list watch]
  persistentvolumeclaims/status                []                 []              [get list watch]
  persistentvolumeclaims                       []                 []              [get list watch]
  pods/log                                     []                 []              [get list watch]
  pods/status                                  []                 []              [get list watch]
  pods                                         []                 []              [get list watch]
  replicationcontrollers/scale                 []                 []              [get list watch]
  replicationcontrollers/status                []                 []              [get list watch]
  replicationcontrollers                       []                 []              [get list watch]
  resourcequotas/status                        []                 []              [get list watch]
  resourcequotas                               []                 []              [get list watch]
  serviceaccounts                              []                 []              [get list watch]
  services/status                              []                 []              [get list watch]
  services                                     []                 []              [get list watch]
  controllerrevisions.apps                     []                 []              [get list watch]
  daemonsets.apps/status                       []                 []              [get list watch]
  daemonsets.apps                              []                 []              [get list watch]
  deployments.apps/scale                       []                 []              [get list watch]
  deployments.apps/status                      []                 []              [get list watch]
  deployments.apps                             []                 []              [get list watch]
  replicasets.apps/scale                       []                 []              [get list watch]
  replicasets.apps/status                      []                 []              [get list watch]
  replicasets.apps                             []                 []              [get list watch]
  statefulsets.apps/scale                      []                 []              [get list watch]
  statefulsets.apps/status                     []                 []              [get list watch]
  statefulsets.apps                            []                 []              [get list watch]
  horizontalpodautoscalers.autoscaling/status  []                 []              [get list watch]
  horizontalpodautoscalers.autoscaling         []                 []              [get list watch]
  cronjobs.batch/status                        []                 []              [get list watch]
  cronjobs.batch                               []                 []              [get list watch]
  jobs.batch/status                            []                 []              [get list watch]
  jobs.batch                                   []                 []              [get list watch]
  daemonsets.extensions/status                 []                 []              [get list watch]
  daemonsets.extensions                        []                 []              [get list watch]
  deployments.extensions/scale                 []                 []              [get list watch]
  deployments.extensions/status                []                 []              [get list watch]
  deployments.extensions                       []                 []              [get list watch]
  ingresses.extensions/status                  []                 []              [get list watch]
  ingresses.extensions                         []                 []              [get list watch]
  networkpolicies.extensions                   []                 []              [get list watch]
  replicasets.extensions/scale                 []                 []              [get list watch]
  replicasets.extensions/status                []                 []              [get list watch]
  replicasets.extensions                       []                 []              [get list watch]
  replicationcontrollers.extensions/scale      []                 []              [get list watch]
  ingresses.networking.k8s.io/status           []                 []              [get list watch]
  ingresses.networking.k8s.io                  []                 []              [get list watch]
  networkpolicies.networking.k8s.io            []                 []              [get list watch]
  poddisruptionbudgets.policy/status           []                 []              [get list watch]
  poddisruptionbudgets.policy                  []                 []              [get list watch]
</code></pre>

<p>Summary of <a href="https://github.com/docker/for-mac/issues/3694" rel="nofollow noreferrer">issue</a> from <a href="https://www.portainer.io/blog/docker-desktop-kubernetes-not-enforcing-rbac-rules" rel="nofollow noreferrer">Neil Cresswell on portainer.io</a></p>
<p>By default, Docker Desktop and their embedded Kubernetes offering does <strong>NOT</strong> enforce any RBAC rules. It will let you create RBAC rules, but it wont enforce them.</p>
<p><strong>ALL</strong> service accounts automatically receive <strong>cluster-admin</strong> role <strong>BY DEFAULT</strong>.</p>
<p>The article says this can be easily fixed by running <code>kubectl delete clusterrolebinding docker-for-desktop-binding</code> and it will start enforcing RBAC rules.</p>
<p>You can also <a href="https://github.com/docker/for-mac/issues/4774#issuecomment-658128960" rel="nofollow noreferrer">patch this issue</a> on your own deploys by running:</p>
<pre><code>kubectl apply -f - &lt;&lt;EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: docker-for-desktop-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: system:serviceaccounts:kube-system
EOF
</code></pre>
