can variables hold the boolean result of an expres...
# help
j
can variables hold the boolean result of an expression?
d
Yes, they can
j
so i can put this whole block into a variable?
Copy code
match:
          all:
            of:
              - expr: P.id in ["xxxxxxxxxx"]
              - any:
                  of:
                    - all:
                        of:
                          - expr: has(request.aux_data.jwt.aud)
                          - any:
                              of:
                                - expr: >
                                    "myaud" in request.aux_data.jwt.aud
                                - expr: (request.aux_data.jwt.aud == "myaud")
                          - expr: has(request.aux_data.jwt.org_info)
                          - expr: has(request.aux_data.jwt.org_info.default_org_id)
                          - expr: has(request.aux_data.jwt.org_info.orgs)
                          - expr: type(request.aux_data.jwt.org_info.orgs) == list
                          - expr: >
                              request.aux_data.jwt.org_info.default_org_id == "org_id"
                          - any:
                              of:
                                - expr: request.principal.attr.surrogate_org_id == ""
                                - expr: has(request.principal.attr.surrogate_org_id) == false
                                - expr: request.principal.attr.surrogate_org_id == null
                    # The next section guarantees that the user is a Avengers surrogate user
                    - all:
                        of:
                          - expr: has(request.aux_data.jwt.aud)
                          - expr: >
                              ("myaud" in request.aux_data.jwt.aud)
                          - expr: has(request.aux_data.jwt.org_info)
                          - expr: has(request.aux_data.jwt.org_info.default_org_id)
                          - expr: has(request.aux_data.jwt.org_info.orgs)
                          - expr: type(request.aux_data.jwt.org_info.orgs) == list
                          - expr: has(request.principal.attr.surrogate_org_id)              
                          - expr: >
                              request.principal.attr.surrogate_org_id == "org_id"
                          - expr: >
                              request.aux_data.jwt.org_info.orgs.exists_one(t, t.org_id == "org_id")
this is invalid though
Copy code
apiVersion: api.cerbos.dev/v1
description: Common variables used within the Apatr app
exportVariables:
  name: apatr_common_variables
  definitions:
    super_var:         
      match:
          all:
            of:
              - expr: P.id in ["xxxxxxxxxx"]
              - any:
                  of:
                    - all:
                        of:
                          - expr: has(request.aux_data.jwt.aud)
                          - any:
                              of:
                                - expr: >
                                    "myaud" in request.aux_data.jwt.aud
                                - expr: (request.aux_data.jwt.aud == "myaud")
                          - expr: has(request.aux_data.jwt.org_info)
                          - expr: has(request.aux_data.jwt.org_info.default_org_id)
                          - expr: has(request.aux_data.jwt.org_info.orgs)
                          - expr: type(request.aux_data.jwt.org_info.orgs) == list
                          - expr: >
                              request.aux_data.jwt.org_info.default_org_id == "org_id"
                          - any:
                              of:
                                - expr: request.principal.attr.surrogate_org_id == ""
                                - expr: has(request.principal.attr.surrogate_org_id) == false
                                - expr: request.principal.attr.surrogate_org_id == null
                    # The next section guarantees that the user is a Avengers surrogate user
                    - all:
                        of:
                          - expr: has(request.aux_data.jwt.aud)
                          - expr: >
                              ("myaud" in request.aux_data.jwt.aud)
                          - expr: has(request.aux_data.jwt.org_info)
                          - expr: has(request.aux_data.jwt.org_info.default_org_id)
                          - expr: has(request.aux_data.jwt.org_info.orgs)
                          - expr: type(request.aux_data.jwt.org_info.orgs) == list
                          - expr: has(request.principal.attr.surrogate_org_id)              
                          - expr: >
                              request.principal.attr.surrogate_org_id == "org_id"
                          - expr: >
                              request.aux_data.jwt.org_info.orgs.exists_one(t, t.org_id == "org_id")
file is not valid: [/exportVariables/definitions/super_var: expected string, but got object]
d
A variable can hold a result of CEL expression evaluation.
j
so a single
expr
d
Yes
j
darn.....i gotta rewrite all that
match.any.of
etc
match.all.of
..... ok. i'll try that. thanks!
d
Yes, quite a long boolean expression.
j
yup! i'll break it down into 1 bool expr in 1 var then one final mother of all vars that uses those individual vars
d
I don’t think a variable can reference another variable.
j
omg.....
ok
d
Maybe instead of a mother var, you can use a derived role?
j
well i do but i need to repeat the derivedrole logic elsewhere
d
I see
j
because i want to check if user.id = xxxx and user.derivedRole = "yyyy"
i can't access user.derivedRole
so i have to repeat the logic
so i have 2 derived roles. 1. superman-derivedRole 2. superman-surrogate-derivedRole i have various resource policies where i grant these 2 roles access. i now have a special resource policy that i want to grant to user-X and i want to ensure user-X is either in #1 or #2 above.
if i do not do that last check then there is a chance that user-X will be accessing that resource but that resource does not have valid data for that user.
just to explain. #2 means the user is in wonderwoman-derivedRole but this user is also granted superman-surrogate-derivedRole. so this user can see data related to superman-derivedRole resources.
it's kinda like wonderoman-derivedRole is an auditor and he or she wants to see all financial customer data
maybe i should rethink this....scopes might help?
d
Correct me if I’m wrong. Would it help if you could specify that you need both derived roles? Currently, in a policy, you can specify multiple derived roles, but it is required to have any of them, not all.
j
yes that's right but the problem is when i'm trying to calculate the derivedRole for that special resource
i need to think about this a bit more
ah yes ther'es a simpler way to do this
would be nice if i can reference the derivedRole in P.derivedRole
at least get an array. 🙂
so what i ended up with: 1. the resourcepolicy "FinancialStatements" that grants access to the role "poweruser" 2. the role "poweruser" is assigned to: • userid-xxx • any user with a JWT that has the details to identify the user as an "Auditor"
that problem is the 2nd bullet point
i have a derived role policy for "Auditor"
d
Is “poweruser” a derived role?
j
yes
i had to cut and paste the logic from derived role "Auditor" into the resourcepolicy "FinancialStatements"
d
Is what you were trying to avoid with your original question about variables?
j
yeah
that's my scenario.
Copy code
apiVersion: "api.cerbos.dev/v1"
description: Global Invicta Roles
derivedRoles:
  name: global_invicta_roles
  definitions:
    - name: invicta_cspm_role
      parentRoles: [ "*" ]
      condition:
        match:
          any:
            of:
              - expr: P.id in ["xxxx"]
              - expr: P.derivedRole in ["Auditor"]
that would be nice but it's not possible because of
P.derivedRole
d
Can you declare a set of variables and reference them in these “auditor” and “poweruser” roles?
j
how? i can't because:
Copy code
- all:
                  of:
                    - expr: has(request.aux_data.jwt.aud)
                    - any:
                        of:
                          - expr: >
                              "myaud" in request.aux_data.jwt.aud
                          - expr: (request.aux_data.jwt.aud == "myaud")
                    - expr: has(request.aux_data.jwt.org_info)
                    - expr: has(request.aux_data.jwt.org_info.default_org_id)
                    - expr: has(request.aux_data.jwt.org_info.orgs)
                    - expr: type(request.aux_data.jwt.org_info.orgs) == list
                    - expr: >
                        request.aux_data.jwt.org_info.default_org_id == "Audit Company 1"
                    - any:
                        of:
                          - expr: request.principal.attr.surrogate_org_id == ""
                          - expr: has(request.principal.attr.surrogate_org_id) == false
                          - expr: request.principal.attr.surrogate_org_id == null
that's the condition to give "Auditor" role
multiple
expr
d
I agree, merging this into a single
expr
won’t give you a nice solution.
j
difficult to maintain
so i really need
P.derivedRole
d
The problem with
P.derviedRole
is that it implies there’s a dependency between them. We are thinking about an alternative.
j
ok
d
if you could specify that you need both derived roles “Auditor” and “Poweruser”, you wouldn’t need to repeat the Auditor’s conditions.
A kind of composition instead of inheritance
j
jeeeeeeeeeesus
how stupid i was. you are absolutely right! i went down the wrong rabbit hole!!!!!!!!!!
grrrrrrr!!!
d
Sorry, you can’t do it right now.
j
no no, i rewrote my policy. in the resource policy, i just had to add "Auditor" into the derivedRole that has access to that resource of "Financial Statements". my god...i should be slapping myself silly now
Copy code
apiVersion: api.cerbos.dev/v1
resourcePolicy:
  resource: test_resource
  version: development
  importDerivedRoles:
  - global_invicta_roles
  - auditor_global_roles
  rules:
  - actions:
    - read
    - subscribed
    effect: EFFECT_ALLOW
    derivedRoles:
    - auditor_role
    - invicta_cspm_role
    condition:
      match:
        expr: request.resource.attr.data_org_id == "xxxxxx"
d
But what if a user doesn’t have
invicta_cspm_role
role?
j
you mean
derivedRoles
is evaluated as an
and
condition?
d
Copy code
derivedRoles:
    - auditor_role
    - invicta_cspm_role
This means EITHER of these roles
j
the user needs both roles?
yes i want
EITHER
/
OR
condition
d
Ah, ok
j
invicta_cspm_role is a role that a bank will hold
auditor_role belongs to an auditor
and
expr: request.resource.attr.data_org_id == "xxxxxx"
ensures that the resource is only valid if it is attached to THAT bank
so if an insurance company comes along, the auditor cannot access "Financial Statements" because
expr: request.resource.attr.data_org_id == "xxxxxx"
wouldn't match for that insurance company
if i ever needed the "AND" condition, i would have to write a different derived role policy that combines both auditor and invicta_cspm_role
maybe call it invicta_cspm_auditor_role
d
if i ever needed the “AND” condition, i would have to write a different derived role policy that combines both auditor and invicta_cspm_role
We had this idea, but there’s no ETA yet.
j
alright!