kuberneteskubernetes-rbac

Kuberentes RBAC rule to allow creating Jobs only from a CronJob


Is it possible to create a kubernetes RBAC rule that allows creating a Job from an existing CronJob, but prevents creating a Job any other way?

We want to keep our clusters tightly locked down to avoid arbitrary deployments not managed by CICD - but we also need to facilitate manual testing of CronJobs, or rerunning failed jobs off schedule. I'd like developers to be able to run a command like:

kubectl create job --from=cronjob/my-job my-job-test-run-1

But not be able to run something like:

kubectl create job my-evil-job -f evil-job.yaml

Is that possible?


Solution

  • In this scenario in order to successfully execute this command:

    kubectl create job --from=cronjob/<cronjob_name>  
    

    User/ServiceAccount should have proper RBAC rules (at least two from the output provided below, create Jobs and get CronJobs.

    In first example I granted access to create Jobs and get CronJobs and I was able to create Job and Job --from CronJob

    user@minikube:~$ cat test_role
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      namespace: default
      name: job
    rules:
    - apiGroups: ["batch"]
      resources: ["jobs"]
      verbs: ["create"]
    - apiGroups: ["batch"]
      resources: ["cronjobs"]
      verbs: ["get"]
    user@minikube:~$ kubectl create job --image=inginx testjob20
    job.batch/testjob20 created
    user@minikube:~$ kubectl create job --from=cronjobs/hello testjob21
    job.batch/testjob21 created
    

    But if I granted access only to create Job without get CronJob, I was be able to create Job but not to create Job --from CronJob

    user@minikube:~$ cat test_role
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      namespace: default
      name: job
    rules:
    - apiGroups: ["batch"]
      resources: ["jobs"]
      verbs: ["create"]
    user@minikube:~$ kubectl create job --image=nginx testjob3
    job.batch/testjob3 created
    user@minikube:~$ kubectl create job --from=cronjobs/hello testjob4
    Error from server (Forbidden): cronjobs.batch "hello" is forbidden: User "system:serviceaccount:default:t1" cannot get resource "cronjobs" in API group "batch" in the namespace "default"
    

    When I deleted access to create Jobs, I couldn't create Job and also Job --from CronJob

    user@minikube:~$ cat test_role
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      namespace: default
      name: job
    rules:
    - apiGroups: ["batch"]
      resources: ["cronjobs"]
      verbs: ["get"]
    user@minikube:~$ kubectl create job --image=inginx testjob10
    error: failed to create job: jobs.batch is forbidden: User "system:serviceaccount:default:t1" cannot create resource "jobs" in API group "batch" in the namespace "default"  
    user@minikube:~$ kubectl create job --from=cronjobs/hello testjob11
    error: failed to create job: jobs.batch is forbidden: User "system:serviceaccount:default:t1" cannot create resource "jobs" in API group "batch" in the namespace "default"
    

    As you can see if User/ServiceAccount doesn't have both permission in this scenario it's impossible to create (Job or Job --from CronJob) so it's impossible to create such restrictions using only RABC rules.

    One possible solution is to split this permission into two different User/ServiceAccount for two different tasks (first user can create Jobs + get CronJobs, second user without permission to create Jobs).

    Another possibility is to try to use k8s admission Controller with f.e. Open Policy agent