One of the key Kubernetes security concepts is that workload identity is tied back to information that the orchestrator has. The orchestrator is actually the authoritative entity for what the actual workloads are in the platform.
Kubernetes uses labels to select objects and to identify collections of objects that satisfy certain conditions. We, and others in the Kubernetes networking space, often talk about using Kubernetes ‘labels’ as identity bearers. Label selectors are the primary thing that native Kubernetes network policy uses to identify the pods which a policy matches on. (Tigera Secure and Tigera’s Project Calico follow the same paradigm and provide even richer network policy capabilities using labels to identify collections of workloads.) Here is an example of a pod definition:
apiVersion: v1 kind: Pod metadata: Labels: name: nginx frontend: server spec: containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80
Kubernetes Role-Based Authentication (RBAC) allows for the ability to control who can manipulate individual API objects, some examples of which include Pods, Services, Deployments, and Service Accounts. This means that it is possible to grant (or deny) a user or group of users the ability to manipulate given API objects (such as launch pods, destroy services, etc.)
It should be noted that labels are not an API object, but part of other API objects. That means that if you grant a developer the permissions to create pods (create permissions on the Pod API object) they can add any labels that they want to that pod).
In many organizations, this is sufficient as there has to be a level of trust in the people actually creating and launching the workloads. However, in some organizations, especially ones with multiple groups with their own security responsibilities, or organizations with specific requirements, such as compliance or regulatory concerns, not having the ability to control who can attach certain labels on workloads is a problem.
It would seem that it would be easy, from a network policy implementation perspective, to control what labels are honored, labels are used for many things in Kubernetes, not just network policy. It could lead to confusion and chaos if certain parts of Kubernetes ‘honored’ a given label, and other parts of the platform did not.
A solution to this requirement comes in the form of another API object that can be attached to workloads in Kubernetes is the service account. Below is an example of a service account API object, and pod with that service account:
apiVersion: v1 kind: ServiceAccount metadata: name: build-robot apiVersion: v1 kind: Pod metadata: name: my-pod spec: serviceAccountName: build-robot Label: automation == “build”
Service accounts (since they are an API object) are discretely RBAC controlled which means that each service account can have its own RBAC permissions. Furthermore, service accounts, like all other Kubernetes objects, can themselves have labels. This means that there is a fairly fine-grained RBAC controlled label artifact that is available in Kubernetes.
It happens that we at Tigera have extended our network policy implementation to use Service Accounts, and labels in service accounts as another ‘selector’ in our policy definition.
The following is an example of a Calico network policy, first matching a label, and next matching a service account can be seen below:
apiVersion: projectcalico.org/v3 kind: GlobalNetworkPolicy metadata: name: allow-frontend spec: selector: custDB == ‘server’ types: - Ingress ingress: - action: Allow protocol: TCP source: selector: frontend == ‘server’ destination: ports: - 8080 apiVersion: projectcalico.org/v3 kind: GlobalNetworkPolicy metadata: name: allow-frontend spec: selector: custDB == ‘server’ types: - Ingress ingress: - action: Allow protocol: TCP source: serviceAccounts: selector: automation == ‘build’ destination: ports: - 8080
There are some things to be aware of, when using service accounts, however. Each pod can only have a single service account bound to it. You can think of a service account as being a unique pod identifier.
However, since service accounts can also be labeled (like any other Kubernetes API object). This means that those labels can be used to create ‘groups’ of service accounts, just like label selectors for pods, services, network policies which follow standard Kubernetes practice.
Since Service Accounts are a separate API object, you can use RBAC to restrict which users can manipulate the service account and its labels. This allows the designation of specific trusted entities (code and/or people) who can grant the necessary and required selectors (service account labels) to a given service account, and make that service account available in a given namespace. This capability, available in both Tigera Secure and Tigra’s Project Calico, provides a tighter level of control over how policies are applied in your cluster.