Slide 1

Slide 1 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer Beyond RBAC Implementing Relation-based Access Control for Kubernetes with OpenFGA Jonathan Whitaker Staff Software Engineering, Okta/Auth0 Lucas Käldström Cloud Native Researcher, CNCF Ambassador

Slide 2

Slide 2 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer Agenda ● Overview of OpenFGA ● Overview of Kubernetes Authorization and RBAC ● Modeling Kubernetes with Relationship-based Access Control (ReBAC) ● Demo of a Kubernetes Authorizer with OpenFGA ● Beyond RBAC - what comes next? ● Q/A

Slide 3

Slide 3 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer ● Flexible and performant engine built to solve Fine-Grained Authorization (FGA) ● Inspired by Google's Zanzibar paper, which describes how authorization for all of Google's services was built ● CNCF Sandbox project - OpenFGA on CNCF ● Created and actively maintained by Okta/Auth0 ● Growing community and various project integrations ○ Please join the community! https://openfga.dev What is OpenFGA?

Slide 4

Slide 4 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer Developer Experience with OpenFGA 1. App developer specifies an authorization model a. “Users can view folders, folders contain documents” 2. Write or import relationship data a. “User Lucas can view folder ‘customers’, and folder ‘customers’ has document ‘secret’” 3. Query OpenFGA a. “Can user Lucas view document ‘secret’?” ⇒ true b. “What documents can user Lucas view?” ⇒ [“document:secret”, … ]

Slide 5

Slide 5 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer OpenFGA Tooling & Ecosystem

Slide 6

Slide 6 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer OpenFGA Deployment Models ● Embed as library in Go ● Deploy as sidecar service ● Deploy as standalone service ○ Horizontally scalable ○ Persistence in popular databases (Postgres, MySQL) or in-memory ○ Accessible through gRPC or HTTP

Slide 7

Slide 7 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer FGA Models: Overview ● Relationship Tuples establish concrete paths in the graph - defined as {src_node, relation, dst_node} user:lucas document:secret read delete actual relation possible relation Concrete Tuples: user:lucas document:secret read ● Modeled as a graph with types (nodes) and relations (directed edges). ● Relations define relationships between related types.

Slide 8

Slide 8 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer RBAC with ReBAC user:lucas rolebinding:getters resource:pods assignee assignee get rolebinding:deleters role:deleter assignee assignee delete Evaluating Check(resource:pods# get@user:lucas) role:getter assignee assignee assignee assignee

Slide 9

Slide 9 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer RBAC with ReBAC user:lucas rolebinding:getters resource:pods assignee assignee get rolebinding:deleters role:deleter assignee assignee delete Evaluating Check(resource:pods# get@user:lucas) role:getter assignee assignee assignee assignee

Slide 10

Slide 10 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer RBAC with ReBAC user:lucas rolebinding:getters resource:pods assignee assignee get rolebinding:deleters role:deleter assignee assignee delete Evaluating Check(resource:pods# get@user:lucas) → {allowed: true} role:getter assignee assignee assignee assignee

Slide 11

Slide 11 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer RBAC with ReBAC user:lucas rolebinding:getters resource:pods assignee assignee get rolebinding:deleters role:deleter assignee assignee delete Evaluating Check(resource:pods# delete@user:lucas) role:getter assignee assignee assignee assignee

Slide 12

Slide 12 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer RBAC with ReBAC user:lucas rolebinding:getters resource:pods assignee assignee get rolebinding:deleters role:deleter assignee assignee delete Evaluating Check(resource:pods# delete@user:lucas) role:getter assignee assignee assignee assignee

Slide 13

Slide 13 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer RBAC with ReBAC user:lucas rolebinding:getters resource:pods assignee assignee get rolebinding:deleters role:deleter assignee assignee delete Evaluating Check(resource:pods# delete@user:lucas) → {allowed: true} role:getter assignee assignee assignee assignee

Slide 14

Slide 14 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer FGA Model Example

Slide 15

Slide 15 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer FGA Model Rewrites 1. Computed userset rewrites “If you can edit the document, then you can view the document” 2. Inheritance (Tuple to userset) “If you can view the parent folder, then you can view the document” 3. Set operations a. Union b. Intersection c. Exclusion

Slide 16

Slide 16 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer Kubernetes Authorization and RBAC

Slide 17

Slide 17 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer Kubernetes: API Basic Concepts API Groups apiVersion: apps/v1 apiVersion: networking.k8s.io/v1 Resources kind: Deployment kind: NetworkPolicy Verbs ● GET ● POST ● PUT ● PATCH ● DELETE Resource URIs to Authorization Attributes ● GET /apis/apps/v1/deployments/my-deployment ○ get ● GET /apis/apps/v1/deployments ○ list ● GET /apis/apps/v1/deployments?watch=1 ○ watch ● POST /apis/apps/v1/deployments ○ create ● PUT /apis/apps/v1/deployments/my-deployment ○ update ● PATCH /apis/apps/v1/deployments/my-deployment ○ patch ● DELETE /apis/apps/v1/deployments/my-deployment ○ delete

Slide 18

Slide 18 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer Kubernetes Authorizer The Authorizer determines if a user can perform a given action (before the body is deserialized) Attributes (Input): ● User Info {Name, Groups, UID} ● API group: apps ● Resource: Deployment ● Verb: create ● (Object Name) ● (Namespace) Response Output: ● Allow ● NoOpinion (RBAC never denies, it is purely additive) ● Deny Kubernetes supports multiple Authorizers in a chain

Slide 19

Slide 19 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer RBAC in Kubernetes: Roles and Role Bindings apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: reconcile-deployments rules: - apiGroups: ["apps"] verbs: ["get", "list", "watch"] resources: ["deployments"] - apiGroups: ["apps"] verbs: ["update"] resources: ["deployments/status"] apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: deployment-users roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: reconcile-deployments subjects: - apiGroup: rbac.authorization.k8s.io kind: User name: lucas - apiGroup: rbac.authorization.k8s.io kind: Group name: team-members ● Additionally, Roles and RoleBinding (scoped to a namespace) ● Namespaces provide isolation of groups of resources within a cluster ClusterRole - defines the actions an actor can perform on the given resources (cluster-wide). ClusterRoleBinding - binds a single role to one or more subjects.

Slide 20

Slide 20 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer ClusterRole-owned Tuple RBAC in Kubernetes: Roles and Role Bindings apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: reconcile-deployments rules: - apiGroups: ["apps"] verbs: ["get", "list", "watch"] resources: ["deployments"] - apiGroups: ["apps"] verbs: ["update"] resources: ["deployments/status"] resource: apps.deployments resource: apps.deployments/status clusterrole: reconcile-deployments #assignee update get list watch apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: deployment-users roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: reconcile-deployments subjects: - apiGroup: rbac.authorization.k8s.io kind: User name: lucas - apiGroup: rbac.authorization.k8s.io kind: Group name: team-members

Slide 21

Slide 21 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer ClusterRole-owned Tuple ClusterRoleBinding-owned Tuple RBAC in Kubernetes: Roles and Role Bindings apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: reconcile-deployments rules: - apiGroups: ["apps"] verbs: ["get", "list", "watch"] resources: ["deployments"] - apiGroups: ["apps"] verbs: ["update"] resources: ["deployments/status"] resource: apps.deployments resource: apps.deployments/status clusterrole: reconcile-deployments #assignee clusterrolebinding: deployment-users #assignee update get list watch apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: deployment-users roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: reconcile-deployments subjects: - apiGroup: rbac.authorization.k8s.io kind: User name: lucas - apiGroup: rbac.authorization.k8s.io kind: Group name: team-members user: lucas group: team-members assignee assignee assignee

Slide 22

Slide 22 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer Mapping Kubernetes API objects to Tuples We propose a controller that: ● Processes Kubernetes API objects containing authorization policies (such as RBAC definitions), and ● Derives the desired tuples for the relationship graph based on the API object and declarative mapping policy ● Writes these Tuples to OpenFGA

Slide 23

Slide 23 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer Concrete Tuple Contextual Tuple GET /apis/apps/v1/namespaces/team-1/deployments/my-deployment user:lucas resourceinstance: apps.deployments/ my-deployment get Graph-based Authorizer Implementation

Slide 24

Slide 24 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer GET /apis/apps/v1/namespaces/team-1/deployments/my-deployment get user:lucas clusterrole:view-all-apps resource:apps.* resourceinstance: apps.deployments/ my-deployment get Concrete Tuple Contextual Tuple Graph-based Authorizer Implementation

Slide 25

Slide 25 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer GET /apis/apps/v1/namespaces/team-1/deployments/my-deployment get assignee user:lucas clusterrole:view-all-apps resource:apps.* resourceinstance: apps.deployments/ my-deployment get Concrete Tuple Contextual Tuple Graph-based Authorizer Implementation

Slide 26

Slide 26 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer GET /apis/apps/v1/namespaces/team-1/deployments/my-deployment get assignee get user:lucas clusterrole:view-all-apps resource:apps.* resource:apps.deployments resourceinstance: apps.deployments/ my-deployment get Concrete Tuple Contextual Tuple Graph-based Authorizer Implementation

Slide 27

Slide 27 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer GET /apis/apps/v1/namespaces/team-1/deployments/my-deployment get assignee get contains get user:lucas namespace:team-1 clusterrole:view-all-apps role:team-1-view-deploys resource:apps.* resource:apps.deployments resourceinstance: apps.deployments/ my-deployment get Concrete Tuple Contextual Tuple Graph-based Authorizer Implementation

Slide 28

Slide 28 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer GET /apis/apps/v1/namespaces/team-1/deployments/my-deployment get assignee get contains assignee get user:lucas namespace:team-1 clusterrole:view-all-apps role:team-1-view-deploys resource:apps.* resource:apps.deployments resourceinstance: apps.deployments/ my-deployment get Concrete Tuple Contextual Tuple Graph-based Authorizer Implementation

Slide 29

Slide 29 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer GET /apis/apps/v1/namespaces/team-1/deployments/my-deployment get assignee get operates_in contains assignee get AND user:lucas namespace:team-1 clusterrole:view-all-apps role:team-1-view-deploys resource:apps.* resource:apps.deployments resourceinstance: apps.deployments/ my-deployment get Concrete Tuple Contextual Tuple Graph-based Authorizer Implementation

Slide 30

Slide 30 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer Graph-like relations in Kubernetes

Slide 31

Slide 31 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer A node should only see linked pods’ resources node:b pod:foo-1 pod:bar-1 secret:cert-keys configmap:app-cfg persistentvolumeclaim:pvc-1 Implemented statically in Go code by the Node authorizer. ⇒ we want to generalize this for control planes in general. node a cannot see secret cert-keys, pvc-1, nor pv-1 node b cannot see pvc-0 nor pv-0 node:a pod:bar-0 persistentvolumeclaim:pvc-0 serviceaccount:sa-1 persistentvolume:pv-1 persistentvolume:pv-0

Slide 32

Slide 32 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer Let’s generalize that through declarative config deployment:foo replicaset:foo-2 replicaset:foo-1 pod:foo-2-a pod:foo-2-b pod:foo-1-a RBAC can allow access to individual resource instances, but you need to specify the names ⇒ not scalable and often names are random Idea is to provide a declarative way to define desired authorization policies of related objects in Kubernetes (and beyond) Can be useful for limiting e.g. the number of controllers that need cluster-wide access to read/write all secrets.

Slide 33

Slide 33 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer Goals: Kubernetes Authorizer with OpenFGA ● Implement RBAC & Node Authorizer with OpenFGA ● Support existing RBAC APIs ● Showcase extensibility of Kubernetes ● Prototype more fine-grained authorization paradigms

Slide 34

Slide 34 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer Kubernetes API object Kubernetes with OpenFGA Demo ReBAC Authorizer kube-api- to-tuples- controller API Server async API object watch async tuple write sync check sync webhook OpenFGA Tuples

Slide 35

Slide 35 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer Going Beyond RBAC in Kubernetes ● Implement the RulesReview using OpenFGA ListObjects API ● Expanding the scope of authorization to the so-called “validating admission” stage ● Define a generic CRD API for declaratively specifying how to map an API object to Tuples using CEL ● Integrate support in controllers (e.g. using controller-runtime) for reconciling only subsets of items of a given resource ● Experiment further with ABAC or listing by e.g. label selector ● Integration with kcp for generic control planes ● Enforce immutability of links between nodes through an admission controller ● Integrate with other sources of authorization data (e.g. authentication providers) ● Add possibility to specify Deny roles

Slide 36

Slide 36 text

@kubernetesonarm + @openfga github.com/luxas/kube-rebac-authorizer Thanks! Jonathan Whitaker Staff Software Engineering, Okta/Auth0 GitHub: @jon-whit [email protected] Lucas Käldström Cloud Native Researcher, CNCF Ambassador GitHub: @luxas LinkedIn: @luxas Twitter: @kubernetesonarm [email protected]