<p>I have full admin access to a GKE cluster, but I want to be able to create a kubernetes context with just read only privileges. This way I can prevent myself from accidentally messing with the cluster. However, I still want to be able to switch into a mode with full admin access temporarily when I need to make changes (I would probably use cloud shell for this to fully distinguish the two)</p>

<p>I haven't much docs about this - it seems I can set up roles based on my email but not have two roles for one user.</p>

<p>Is there any way to do this? Or any other way to prevent fat-finger deleting prod? </p>

John Howard
<p>There are a few ways to do this with GKE. A <code>context</code> in your KUBECONFIG consists of a <code>cluster</code> and a <code>user</code>. Since you want to be pointing at the same <code>cluster</code>, it's the <code>user</code> that needs to change. Permissions for what actions <code>user</code>s can perform on various resources can be controlled in a couple ways, namely via <a href="https://cloud.google.com/kubernetes-engine/docs/how-to/iam" rel="nofollow noreferrer">Cloud IAM policies</a> or via <a href="https://cloud.google.com/kubernetes-engine/docs/how-to/role-based-access-control" rel="nofollow noreferrer">Kubernetes RBAC</a>. The former applies project-wide, so unless you want to create a subject that has read-only access to <em>all</em> clusters in your project, rather than a specific cluster, it's preferable to use the more narrowly-scoped Kubernetes RBAC.</p>

<p>The following types of subjects can authenticate with a GKE cluster and have Kubernetes RBAC policies applied to them (see <a href="https://cloud.google.com/kubernetes-engine/docs/how-to/role-based-access-control#rolebinding" rel="nofollow noreferrer">here</a>):</p>

<ol>
<li>a registered (human) GCP user</li>
<li>a Kubernetes ServiceAccount</li>
<li>a GCloud IAM service account</li>
<li>a member of a G Suite Google Group</li>
</ol>

<p>Since you're not going to register another human to accomplish this read-only access pattern and G Suite Google Groups are probably overkill, your options are a Kubernetes ServiceAccount or a GCloud IAM service account. For this answer, we'll go with the latter.</p>

<p>Here are the steps:</p>

<ol>
<li>Create a GCloud IAM service account in the same project as your Kubernetes cluster.</li>
<li>Create a local <code>gcloud</code> configuration to avoid cluttering your default one. Just as you want to create a new KUBECONFIG <code>context</code> rather than modifying the <code>user</code> of your current <code>context</code>, this does the equivalent thing but for <code>gcloud</code> itself rather than <code>kubectl</code>. Run the command <code>gcloud config configurations create &lt;configuration-name&gt;</code>.</li>
<li>Associate this configuration with your GCloud IAM service account: <code>gcloud auth activate-service-account &lt;service_account_email&gt; --key-file=&lt;/path/to/service/key.json&gt;</code>.</li>
<li><p>Add a <code>context</code> and <code>user</code> to your KUBECONFIG file so that you can authenticate to your GKE cluster as this GCloud IAM service account as follows:</p>

<pre><code>contexts:
- ...
- ...
- name: &lt;cluster-name&gt;-read-only
  context:
    cluster: &lt;cluster-name&gt;
    user: &lt;service-account-name&gt;
users:
- ...
- ...
- name: &lt;service-account-name&gt;
  user:
    auth-provider:
      name: gcp
      config:
        cmd-args: config config-helper --format=json --configuration=&lt;configuration-name&gt;
        cmd-path: &lt;/path/to/gcloud/cli&gt;
        expiry-key: '{.credential.token_expiry}'
        token-key: '{.credential.access_token}'
</code></pre></li>
<li><p>Add a <code>ClusterRoleBinding</code> so that this subject has read-only access to the cluster:</p>

<pre><code>$ cat &lt;&lt;EOF | kubectl apply -f -
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: &lt;any-name&gt;
subjects:
- kind: User
  name: &lt;service-account-email&gt;
roleRef:
  kind: ClusterRole
  name: view
  apiGroup: rbac.authorization.k8s.io
EOF
</code></pre></li>
</ol>

<p>Try it out:</p>

<pre><code>$ kubectl use-context &lt;cluster-name&gt;-read-only
$ kubectl get all --all-namespaces
# see all the pods and stuff
$ kubectl create namespace foo
Error from server (Forbidden): namespaces is forbidden: User "&lt;service-account-email&gt;" cannot create resource "namespaces" in API group "" at the cluster scope: Required "container.namespaces.create" permission.

$ kubectl use-context &lt;original-namespace&gt;
$ kubectl get all --all-namespaces
# see all the pods and stuff
$ kubectl create namespace foo
namespace/foo created
</code></pre>
