4

I am trying to allow some users in my org to forward ports to our production namespace in Kubernetes. However, I don't want them to be able to forward ports to all services. I want to restrict access to only certain services. Is this possible?

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: allow-port-forward-for-deployment-a
rules:
- apiGroups: [""]
  resources: ["pods/portforward"]
  verbs: ["get", "list", "create"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: allow-port-forward-for-deployment-a
  namespace: production
subjects:
- kind: User
  name: "xyz@org.com"
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: allow-port-forward-for-deployment-a
  apiGroup: rbac.authorization.k8s.io

The above set up allows all services, but I don't want that.

VBoi
  • 349
  • 5
  • 21

4 Answers4

6

I believe you can't. According to the docs

Resources can also be referred to by name for certain requests through the resourceNames list. When specified, requests can be restricted to individual instances of a resource. To restrict a subject to only “get” and “update” a single configmap, you would write:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: configmap-updater
rules:
- apiGroups: [""]
  resources: ["configmaps"]
  resourceNames: ["my-configmap"]
  verbs: ["update", "get"]

Note that create requests cannot be restricted by resourceName, as the object name is not known at authorization time. The other exception is deletecollection.

Since you want to give the user permissions to create the forward ports, I don't think you can.

Jose Armesto
  • 12,794
  • 8
  • 51
  • 56
3

These rules worked for me

   kind: Role
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      namespace: default
      name: port-forward
    rules:
    - apiGroups: [""]
      resources: ["pods/portforward"]
      verbs: ["get", "create"]
    - apiGroups: [""]
      resources: ["pods", "services"]
      verbs: ["get", "list"]
  • Remember that Stack Overflow isn't just intended to solve the immediate problem, but also to help future readers find solutions to similar problems, which requires understanding the underlying code. This is especially important for members of our community who are beginners, and not familiar with the syntax. Given that, **can you [edit] your answer to include an explanation of what you're doing** and why you believe it is the best approach? – Jeremy Caney May 02 '22 at 18:52
0

Assuming users already have access to your kubernetes cluster and relevant namespace. They can simply port-forward local port to a pod (resource) port.

How can you do this? kubectl port-forward <POD_NAME> <LOCAL_PORT>:<POD_PORT>

See Documentation

Quoting from the document - kubectl port-forward allows using resource name, such as a pod name, to select a matching pod to port forward to since Kubernetes v1.10.

Refer this article if you wish, this nicely explains when you would need RBAC vs kubectl port-forward RBAC could have been useful only when, you wanted person or a group of people only to port-forward for any services in a relevant namespace in your kubernetes cluster.

sulabh chaturvedi
  • 3,608
  • 3
  • 13
  • 25
0

Workaround A: StatefulSets and resourceNames

It is possible to restrict port forwarding to a pod with a specific name. resourceNames refer to resources, not subresources:

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: allow-port-forward-for-deployment-a
rules:
- apiGroups: [""]
  resources: ["pods/portforward"]
  resourceNames: ["my-app"]
  verbs: ["create"]

A StatefulSet generates predictable pod names, but is different from a ReplicaSet and might not fit your use case.

Workaround B: Jump pod and NetworkPolicy

Sketch:

  • A StatefulSet that runs kubectl port-forward services/my-service inside the cluster (JUMP).
  • A NetworkPolicy which restricts traffic from pods belonging to JUMP to the target service
  • RBAC which restricts creation of subresource portforward to the pods of JUMP up to a predefined maximum number of replicas resourceNames: ["jump-0", "jump-1", ..., "jump-N"].
muxmuse
  • 385
  • 2
  • 9