ADRXXX: Authorization decision layer
-
Status: draft
-
Deciders: TBD
-
Date: 2024-01-18
Technical Story: https://github.com/stackabletech/issues/issues/439
Problem Statement
The Stackable Data Platform provides the OpenPolicyAgent as a policy engine, but we currently do not supply examples or rule frameworks to the users to easily get started with writing authorization policies.
We want to supply a rego rule library that platform users can use as a default or as a starting point to write their own Rego rules. These rules (and accompanying data structures) should expose all the product specifics that each product offers. A simplified and abstracted authorization layer will be built later, on top of this one.
Decision Drivers
Users can already write their own rego rules, but we want to make it easier for them and allow them to only write JSON policies. At the same time we still want them to have as much control over the product as possible, without having to write their own Rego rules.
Proposed design
We have specific rego rules per product. These need to be highly specific, because every authorizer has a different request structure.
While there are some commonalities across products (they all have a 'resource' concept), details are product specific and difficult to generalize without losing out on fine grained control. We want to keep as much control as possible.
We can also keep it close to what the software is already doing - in the case of Trino - which makes it easier for users that are migrating.
The RegoRules are deployed by the product operator as ConfigMaps.
The package name contains the version of the ruleset, the product and the product version: stackable.v1.trino.v439
Should we simply version the stackable rules with the platform version? |
Cluster/Stacklet information in the requests
Resources are already organized hierarchically, for example in Trino: Catalog, Schema, Table. The Stacklet sits on top of this, and can be seen as another layer. Because of this, it makes sense to add the Stacklet name, namespace and labels to the authorization request.
The information could be added by the specific authorizer plugin, but at least for Kafka and Trino, this would require patching the upstream authorizer.
Alternatively we could add a little intermediate package:
package enrichRequest.simpleTrino # auto generated package name
import rego.v1
import myRules # package name taken from the clusterConfig
allow if {
myRules.allow with input as { # package name taken from the clusterConfig
"product": "trino",
"cluster": { # the name and labels are taken from the kubernetes metadata
"name": "simple-trino",
"namespace": "foo",
"labels": {
"dev": true
}
},
"request": input
}
}
This could be generated by the product operators and would be "invisible" to the user.
Using the Stackable Rego Framework
Currently, the user specifies a package
when using the OPA authorizer.
kind: TrinoCluster
metadata:
name: simple-trino
labels:
dev: true
spec:
image:
productVersion: "428"
clusterConfig:
authorization:
opa:
configMapName: my-opa
package: myRules
To make it easy to use the framework, the framework should either be the default (and is maybe versioned with the platform version) or you select the version of the rule framework like this:
kind: TrinoCluster
metadata:
name: simple-trino
labels:
dev: true
spec:
image:
productVersion: "428"
clusterConfig:
authorization:
opa:
configMapName: my-opa
stackableRules: v1