hi! I'm looking for some help in policy building: ...
# help
s
hi! I'm looking for some help in policy building: Can variables be assigned conditionally? Like derivedRoles, which can have a whole list of (nested) conditions before they get set. Does the same work inside variables as well? My use case is that I my Principle.roles -list contains just a set of guids. One of the guids entails that the user is from a specific 'tenant'. This tenant variable can be 1:1 compared with the tenant-name in the Resource. So ideally I'd like to rewrite the guid to a tenant-name very early in the cerbos processing. So that the actual policies can remain simple. Any hints? This is what I use at the moment:
Copy code
# Derive roles from AzureAD Group GUID
    - name: device_mgmt_read
      parentRoles:
        - default
      condition:
        match:
          any:
            of:
            # all tenants allowed for this guid
            - expr: ("9a0d9319b51f1ef4" in P.roles)
            # If tenantGUID is used, only allow role derivation when Resource is from the same tenant
            - all:
                of:
                  - expr: R.attr.Tenant == "TENANT1"
                  - expr: ("e25123bf9ca4" in P.roles)
d
Hi Stefan, Variables are CEL expressions, so they can have logical operators equivalent to derivedRole conditions. Do I understand correctly that you want to map the tenant ID to the tenant name and then use the name in the conditions?
s
I think that I want to translate a role into a var, indeed. ‘If guid xx in P.roles => tenant = X If guid yy in P.roles => tenant = Y
d
You can have a map, for example,
P.attr.tenants
, where the key is the tenant ID (GUID), and the value is the tenant’s name. Then, you can collect all the tenant names.
tenantNames: P.roles.map(id, P.attr.tenants[id])
I assumed there were many names because
P.roles
is a list. Another assumption is that there are entries in
P.attr.tenants
for every key from the
P.roles
list.
It might be quicker to sort this out on a call, so feel free to book it.
s
Can the map be stored as another variable as well? You seem to assume the map is sent by the client?
d
Yes, the map can be stored as another variable. I assumed the map was read from the database and sent by the client.
s
the limitation is that we do not have an external (non-cerbos) datasource that maps the guid to tenantname at the moment. I'm struggling with getting it loaded in a Cerbos vars file though. The linter hints that I should input a string, prob syntax related:
{
"apiVersion": "<http://api.cerbos.dev/v1|api.cerbos.dev/v1>",
"exportVariables": {
"name": "tenantmapping",
"definitions": {
"tenantmap": {
"tenant1guid": "tenant1name",
"tenant2guid": "tenant2name"
}
}
}
d
Yes, a variable value should be a string Try this YAML:
Copy code
apiVersion: api.cerbos.dev/v1
exportVariables:
  name: tenantmapping
  definitions:
    tenantmap: > 
        {"tenant1guid": "tenant1name",
        "tenant2guid": "tenant2name"}
s
OK; syntax checks out now. However, my evaluation in the 'derivedRoles' appearently doesn't. How can I debug what's in a variable at each step of the evaluation?
Copy code
- name: device_mgmt_read
      parentRoles:
        - default
      condition: 
        match: 
          expr: R.attr.Tenant in V.tenantNames
Copy code
apiVersion: api.cerbos.dev/v1
exportVariables:
  name: tenantmapping
  definitions:
    tenantmap: >
        {"1111-1111": "tenant1",
        "2222-2222": "tenant2"}
    tenantNames: P.roles.map(id, V.tenantmap[id])
d
You probably have a role in the
P.roles
list that doesn’t exist in the
V.tenantmap
, so the
tenantNames
expression fails to evaluate. You can re-write this expression as
P.roles.filter(r, r in V.tenantmap).map(id, V.tenantmap[id])
. I debug by replacing expressions with the expected value or running
cerbos repl
.
1
s
This syntax works Dennis, thanks!
🙌 1