<p>I know how to use RBAC with X.509 certificates to identify a user of <code>kubectl</code> and restrict them (using <code>Role</code> and <code>RoleBinding</code>) from creating pods of any kind in a namespace. However, I don't know how I can prevent them from putting specific labels on a pod (or any resource) they're trying to create.</p>
<p>What I want to do is something like:</p>
<ol>
<li>Create a <code>NetworkPolicy</code> that only resources in other namespaces with the label <code>group: cross-ns</code> are allowed to reach a resource in the <code>special-namespace</code></li>
<li>Have a user who cannot create pods or other resources with the label <code>group: cross-ns</code></li>
<li>Have another user who <em>can</em> create resources with the label <code>group: cross-ns</code></li>
</ol>
<p>Is this possible?</p>

<p>You can use the Kubernetes-native policy engine called <a href="https://kyverno.io/" rel="nofollow noreferrer">Kyverno</a>:</p>
<blockquote>
<p>Kyverno runs as a dynamic admission controller in a Kubernetes cluster. Kyverno receives validating and mutating admission webhook HTTP callbacks from the kube-apiserver and applies matching policies to return results that enforce admission policies or reject requests.</p>
</blockquote>
<p>A Kyverno policy is a collection of rules that can be applied to the entire cluster (<code>ClusterPolicy</code>) or to the specific namespace (<code>Policy</code>).</p>
<hr />
<p>I will create an example to illustrate how it may work.</p>
<p>First we need to install Kyverno, you have the option of installing Kyverno directly from the latest release manifest, or using Helm (see: <a href="https://kyverno.io/docs/introduction/#quick-start" rel="nofollow noreferrer">Quick Start guide</a>):</p>
<pre><code>$ kubectl create -f https://raw.githubusercontent.com/kyverno/kyverno/main/definitions/release/install.yaml
</code></pre>
<p>After successful installation, let's create a simple <code>ClusterPolicy</code>:</p>
<pre><code>apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: labeling-policy
spec:
  validationFailureAction: enforce
  background: false
  rules:
  - name: deny-rule
    match:
      resources:
        kinds:
        - Pod
    exclude:
      clusterRoles:
      - cluster-admin
    preconditions:
      - key: &quot;{{request.object.metadata.labels.purpose}}&quot;
        operator: Equals
        value: &quot;*&quot;
    validate:
      message: &quot;Using purpose label is not allowed for you&quot;
      deny: {}
</code></pre>
<p>In the example above, only using the <code>cluster-admin</code> <code>ClusterRole</code> you can  modify a Pod with a label <code>purpose</code>.</p>
<p>Suppose I have two users (<code>john</code> and <code>dave</code>), but only <code>john</code> is linked to the <code>cluster-admin</code> <code>ClusterRole</code> via <code>ClusterRoleBinding</code>:</p>
<pre><code>$ kubectl describe clusterrolebinding john-binding
Name:         john-binding
Labels:       &lt;none&gt;
Annotations:  &lt;none&gt;
Role:
  Kind:  ClusterRole
  Name:  cluster-admin
Subjects:
  Kind  Name  Namespace
  ----  ----  ---------
  User  john
</code></pre>
<p>Finally, we can test if it works as expected:</p>
<pre><code>$ kubectl run test-john --image=nginx --labels purpose=test --as john
pod/test-john created

$ kubectl run test-dave --image=nginx --labels purpose=test --as dave
Error from server: admission webhook &quot;validate.kyverno.svc&quot; denied the request:

resource Pod/default/test-dave was blocked due to the following policies

labeling-policy:
  deny-rule: Using purpose label is not allowed for you

$ kubectl get pods --show-labels
NAME        READY   STATUS    RESTARTS   AGE   LABELS
test-john   1/1     Running   0          32s   purpose=test
</code></pre>
<p>More examples with detailed explanations can be found in the <a href="https://kyverno.io/docs/writing-policies/" rel="nofollow noreferrer">Kyverno Writing Policies documentation</a>.</p>
