I am trying to understand security implication of granting kubernetes serviceaccount permission to perform deployments, service creation, etc. The role is clusterrole with namespaced rolebinding.
Use case are using service account to automate/orchestrate some tasks inside cluster. Version is 1.16
Service account can used to grant different access level to different purpose. for developer ClusterRole need to list, get and watch resources but not delete. but Admin can delete and create resources.
If you are developing K8 operator, operator need to communicate with cluster for create, update and delete resources then operator need service with ClusterRoleBinding of all verbs. so that operator can perform all operation on resources. but not good practice to assign full permission to regular deployment.
Let me discuss about this.
According to the docs.
A Role always _sets permissions within a particular namespace__; when you create a Role, you have to specify the namespace it belongs in
ClusterRole, by contrast, is a non-namespaced resource. The resources have different names (Role and ClusterRole) because a Kubernetes object always has to be either namespaced or not namespaced; it can't be both.
A role binding grants the permissions defined in a role to a user or set of users. It holds a list of subjects (users, groups, or service accounts), and a reference to the role being granted. A RoleBinding grants permissions within a specific namespace whereas a ClusterRoleBinding grants that access cluster-wide.
If you want to define a role within a namespace, use a Role; if you want to define a role cluster-wide, use a ClusterRole.
A RoleBinding may reference any Role in the same namespace. Alternatively, a RoleBinding can reference a ClusterRole and bind that ClusterRole to the namespace of the RoleBinding. If you want to bind a ClusterRole to all the namespaces in your cluster, you use a ClusterRoleBinding.
So answering your question - handling ClusterRoles it could be definitively security risk.
The best solution is to grant as minimal permissions as possible.
Grant a role to an application-specific service account (best practice)
Grant a role to the "default" service account in a namespace
Grant a role to all service accounts in a namespace
Grant a limited role to all service accounts cluster-wide (discouraged)
Grant super-user access to all service accounts cluster-wide (strongly discouraged)
There is no one answer for this question because you need to plan and test action/permissions between your application/deployment and kubernetes API. F.e at namesapaced or non namesapced resources, inside one namespace or across the entire cluster.
In you example you can simply use Role/Rolebinding if you are working inside the same namespace. You can use ClusterRole/Rolebinding and extend permissions by additional RoleBinding allowing the ServiceAccount to create new k8s objects into another namespace.
Assuming we are talking about ServiceAccount for deployment, here you can find good advice for "RBAC in Deployments: A use case"
If you create ServiceAccount for your deployment and create appropriate Role/ClusterRole and Rolebinding/ClusterRoleBinding:
you can perform:
kubectl can-i get secrets --as=system:serviceaccount:[namespace]:[service_account_name] -n [target_namespace]
For testing please take a look also at Access Clusters Using the Kubernetes API.
This command will show you if particular ServiceAccount (defined by subject in Rolebinding/ClusterRolebinding) has permissions (defined by verbs in Role/ClusteRole) to get secrets (defined by resources Role/ClusterRole) in specified namespace.
Following this approach you can verify if your deployment has enough permissions to perform all required operation against Kubernetes API.
While working with RBAC in Kubernetes you should consider mentioned below topics:
Have multiple users with different properties, establishing a proper authentication mechanism.
Have full control over which operations each user or group of users can execute.
Have full control over which operations each process inside a pod can execute.
Limit the visibility of certain resources of namespaces.
Related
I'd like to list a specific resource (e.g. pod) across all namespaces in a Kubernetes cluster, but to have the result contain only resources permitted by RBAC.
For example, assume I grant permissions for a certain service account to perform all operations on all pods in 2 namespaces ns1 and ns2. These permissions include the ability to list pods. I can do this using RBAC.
Then I'd like to perform the equivalent of:
kubectl get pods --all-namespaces
... but get only the pods in namespaces ns1 and ns2.
If I grant permissions to list all pods across all namespaces, I get more information than I'd like. And even if that were acceptable, I'd then have to filter the results based on other criteria (e.g. resources to which I granted get access).
Note: I'd like the solution to be based solely on RBAC, as I have little control over the query, since I'm using a graphql wrapper that performs the query programmatically for me and it does it across all namespaces.
What you want is not really possible.
To restrict user access to specific namespace, you would have to create Role and RoleBinding for that namespace.
--all-namespaces flag requires ClusterRole and ClusterRoleBinding to work.
Since RBAC permissions are additive, setting ClusterRole would "overwrite" any perivilege restrictions from Role and RoleBinding.
If a user should only have access to a single namespace he cannot be assigned to a ClusterRole.
Your best bet is to change how graphql wrapper executes the query.
We're trying to create different kuberentes secrets and offer access to specific secrets through specific service accounts that are assigned to pods. For example:
Secrets
- User-Service-Secret
- Transaction-Service-Secret
Service Account
- User-Service
- Transaction-Service
Pods
- User-Service-Pod
- Transaction-Service-Pod
The idea is to restrict access to User-Service-Secretsecret to User-Service service account that is assign to User-Service-Pod. So we can set this all up with the relevant kuberentes resources (i.e. ServiceAccount, Role, RoleBinding), but we realize that this may not be actually enforced, because Transaction-Service-Pod can just as easily read the User-Service-Secret secret when Pod starts up, even though the service account its assign to doesn't have get permission to the User-Service-Secret.
How do we actually enforce the RBAC system?
FYI we are using EKS
First it is important to distinguish between API access to the secret and consuming the secret as an environment variable or a mounted volume.
TLDR:
RBAC controls who can access a secret (or any other resource) using K8s API requests.
Namespaces or the service account's secrets attribute control if a pod can consume a secret as an environment variable or through a volume mount.
API access
RBAC is used to control if an identity (in your example the service account) is allowed to access a resource via the K8s API. You control this by creating a RoleBinding (namespaced) or a ClusterRoleBinding (cluster-wide) that binds an identity to a Role (namespaced) or a ClusterRole (not-namespaced) to your identity (service account). Then, when you assign the service account to a pod by setting the serviceAccountName attribute, running kubectl get secret in that pod or the equivalent method from one of the client libraries would mean you have credentials available to make the API request.
Consuming Secrets
This however is independent of configuring the pod to consume the secret as an environment variable or a volume mount. If the container spec in a pod spec references the secret it is made available inside that container. Note, per container, not per pod. You can limit what secret a pod can mount by having the pods in different namespaces, because a pod can only refer to a secret in the same namespace. Additionally, you can use the service account's secrets attribute, to limit what secrets a pod with thet service account can refer to.
$ kubectl explain sa.secrets
KIND: ServiceAccount
VERSION: v1
RESOURCE: secrets <[]Object>
DESCRIPTION:
Secrets is the list of secrets allowed to be used by pods running using
this ServiceAccount. More info:
https://kubernetes.io/docs/concepts/configuration/secret
ObjectReference contains enough information to let you inspect or modify
the referred object.
You can learn more about the security implications of Kubernetes secrets in the secret documentation.
The idea is to restrict access to User-Service-Secret secret to User-Service service account that is assign to User-Service-Pod. So we can set this all up with the relevant Kubernetes resources (i.e. ServiceAccount, Role, RoleBinding), but we realize that this may not be actually enforced, because Transaction-Service-Pod can just as easily read the User-Service-Secret secret when Pod starts up, even though the service account its assign to doesn't have get permission to the User-Service-Secret.
Yes, this is correct.
This is documented for Kubernetes on privilege escalation via pod creation - within a namespace.
Users who have the ability to create pods in a namespace can potentially escalate their privileges within that namespace. They can create pods that access their privileges within that namespace. They can create pods that access secrets the user cannot themselves read, or that run under a service account with different/greater permissions.
To actually enforce this kind of Security Policies, you probably have to add an extra layer of policies via the admission controller. The Open Policy Agent in the form of OPA Gatekeeper is most likely a good fit for this kind of policy enforcement.
I have bunch of users. Every user should be able to create/change/delete substances in namespaces like *-stage. Namespaces can be added or removed dynamically. I can create ServiceAccount in every namespace and grant privileges.
I created pod in k8s and install kubectl and ssh into it. So every user has access to this pod and can use kubectl. I know that I can mount ServiceAccount secrets to pod. As far as I have different ServiceAccounts for every namespace I don't know how to grant privileges to all *-stage namespaces for every user. I don't want to create cluster-admin ClusterRoleBinding for ServiceAccount, cause users should be able to modify only *-stage namespaces. Can you help me please?
I am posting a community wiki answer based on OP's solution for better visibility:
Actually, I have already solved problem. I create ["*"] role in every
*-stage namespace and bind it to ServiceAccount. Then I mount ServiceAccount to kubectl pod which is available over ssh. So every
user has unlimited access to *-stage namespaces.
Also I am adding links for the official docs regarding ServiceAccount and role-based access control as a supplement.
What is the difference between RoleBinding and ClusterRoleBinding?
And what are the usages of them?
A rolebinding is namespace scoped and clusterrolebinding is cluster scoped i.e across all namespace.
ClusterRoles and ClusterRoleBindings are useful in the following cases:
Give permissions for non-namespaced resources like nodes
Give permissions for resources in all the namespaces of a cluster
Give permissions for non-resource endpoints like /healthz
A RoleBinding can also reference a ClusterRole to grant the permissions defined in that ClusterRole to resources inside the RoleBinding's namespace. This kind of reference lets you define a set of common roles across your cluster, then reuse them within multiple namespaces.
Please refer the Kubernetes documentation here
A Role always sets permissions within a particular namespace; when you create a Role, you have to specify the namespace it belongs in.
ClusterRole, by contrast, is a non-namespaced resource. The resources
have different names (Role and ClusterRole) because a Kubernetes
object always has to be either namespaced or not namespaced; it can’t
be both.
The Cluster variants apply to every namespace. The others only to the namespace they are in.
I have secrets in one namespace added to a Service Account.
If you then ClusterRoleBind this ServiceAccount, will the ServiceAccount then be usable in all namespaces?
You can not use a service account which is contained in namespace from any other namespace. When you give a cluster role to a service account the service account gets permission to do operations defined in the ClusterRole across all namespaces but it's still usable only from the namespace where it's created.
No, service accounts are namespaced and can only be automatically used from within one namespace.