Introduction

In this blog post, we’ll see how and why we need to restrict wildcards in RBACs.

How RBAC works?

We’ll first look at the components that are needed for delegating access based on roles.

Verbs – The verbs are the different actions that can be performed on a resource.

Resource – These are the various API objects to which we’ll give access to.

Subjects – The subjects are the users or processes that require access to the resources.

Now that we know what these are, we’ll try to understand how these are put together to provide role based access. To grant access, we create two things – Role/ClusterRole and RoleBinding/ClusterRoleBinding.

  • The Role will consist of verbs and resources. It tells what actions can be performed on the resource mentioned. By creating a role, we have now sorted out the resource and the actions that can be performed on it.
  • The RoleBinding will contain the subjects and the role. This binds the subjects with the role created earlier. 

NOTE: If a Role is created, we’ll need to create RoleBinding and if a ClusterRole was created, we’ll create ClusterRoleBinding. 

Once both the files have been created/applied, kubernetes now knows what users or processes have access to what resources and what actions can be done on the specified resources.

Why do we need these policies?

As security enthusiasts we have always known the importance of the principle of least privilege. But at times, our human instinct kicks in and we get lazy. The result is, we end up using wildcards (“*’ – all) in verbs and subjects instead of deciding and providing only the required privileges to an user. This is where our policy comes to the rescue. With the policies being implemented in our organization, we can prevent the unaware or the accidental use of the wildcards in Role/ClusterRole and RoleBinding/ClusterRolebinding.

Restrict Wildcards in Verbs

template.yaml

apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: k8sblockwildcardverb
  annotations:
    description: Blocks wildcard in verbs.
spec:
  crd:
    spec:
      names:
        kind: K8sBlockWildCardVerb
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8sblockwildcardverb
        violation[{"msg": msg, "details": {}}]{
        input.review.object.kind == "Role"
        input.review.object.rules[_].verbs[_] == "*"
        msg := "Wildcards are prohibited"
        }
        violation[{"msg": msg, "details": {}}]{
        input.review.object.kind == "ClusterRole"
        input.review.object.rules[_].verbs[_] == "*"
        msg := "Wildcards are prohibited"
        }

Rego Policy explained:

First block:

  1. Check if the kind is “Role”
  2. Check if the verb is “*”
  3. If both are true, deny and display the message. 

Second block:

  1. It’s the same as the first block except it checks if the kind is “ClusterRole”.

Unlike the other opa policies, we have used two “violation” blocks. This is because “OR” operator is not available in Rego and we have to deny if a wildcard is used either in “Role” or “ClusterRole”. So we validate “Role” and “ClusterRole” individually.

constraint.yaml

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sBlockWildCardVerb
metadata:
  name: block-wildcard-verb
spec:
  match:
    kinds:
      - apiGroups: ["rbac.authorization.k8s.io"]
        kinds: ["Role","ClusterRole"]

We have “Role” and “ClusterRole” in “kinds” as we need to validate both.

More information regarding RBAC Authorization can be found here.

deployment-non-violation.yaml

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: allow
rules:
- apiGroups: ["*"]
  resources: ["pods"]
  verbs: ["get", "watch", "list", "create", "delete", "edit"]

This will get deployed as there’s no wildcard used in “verbs”.

deployment-violation.yaml

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: block
rules:
- apiGroups: ["*"]
  resources: ["pods"]
  verbs: ["*"]

This will get denied since “*” wildcard is used in “verbs”.

Restrict Wildcards in Subjects

template.yaml

apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: k8sblockwildcardsubjects
  annotations:
    description: Block Wildcard in subjects
spec:
  crd:
    spec:
      names:
        kind: K8sBlockWildCardSubjects
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8sblockwildcardsubjects
        violation[{"msg": msg, "details": {}}]{
        input.review.object.kind == "RoleBinding"
        input.review.object.subjects[_].name == "*"
        msg := "Wildcards are prohibited"
        }
        violation[{"msg": msg, "details": {}}]{
        input.review.object.kind == "ClusterRoleBinding"
        input.review.object.subjects[_].name == "*"
        msg := "Wildcards are prohibited"
        }

Rego Policy explained:

It’s pretty much the same as the policy expained above. The difference is that here we check if the “kind” is “RoleBinding” or “ClusterRoleBinding” and if the “name” in “subjects” is a wildcard, that is, “*”.

constraint.yaml

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sBlockWildCardSubjects
metadata:
  name: block-wildcard-subjects
spec:
  match:
    kinds:
      - apiGroups: ["rbac.authorization.k8s.io"]
        kinds: ["RoleBinding","ClusterRoleBinding"]

deployment-non-violation.yaml

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: user1-get-pods
subjects:
- apiGroup: ""
  kind: User
  name: "user1"
roleRef:
apiGroup: ""
kind: Role
name: block-wildcard-subjects

This will have no issues as “*” is not used.

deployment-violation.yaml

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: user1-get-pods
subjects:
- apiGroup: ""
  kind: User
  name: "*"
roleRef:
apiGroup: ""
kind: Role
name: block-wildcard-subjects

This will not be allowed as “*” is used.

Though deployment examples of Roles and RoleBindings are only given, the templates and constraints work for ClusterRoles and ClusterRoleBindings also.

NOTE: Just like how the usage of “*” was restricted, the usage of specific verbs can also be restricted.

Conclusion

We’ll never know when someone will use a wildcard because even the best of us sometimes makes mistakes. So it’s always best to implement these policies to restrict wildcards from being used.

Other Related Articles

Practice here:

https://katacoda.com/cloudsecops/courses/opagatekeeper-policy/blockwildcard

References:

Thank you for reading! – Vishal Pranav and Setu Parimi

Sign up for the blog directly here.

Check out our professional services here.

Feedback is welcome! For professional services, fan mail, hate mail, or whatever else, contact [email protected]


0 Comments

Leave a Reply

%d bloggers like this: