Skip to content

Unexpected behavior when using get_query #69

@cadeParade

Description

@cadeParade

Hello,
I am having trouble implementing the get_query method for sql_alchemy in our app. Here's what I've got going on. I am fairly new to Cerbos so it may (likely??) be that something is wrong on my end, but I'm a bit stumped so I'm asking for help.

Simplified policies are as follows:

Policies
# org policy
---

apiVersion: api.cerbos.dev/v1
resourcePolicy:
  resource: org
  version: default
  importDerivedRoles:
  - common_roles
  rules:
      effect: EFFECT_ALLOW
    - actions: ['org.read']
      derived_roles: [
        'OrgViewer',
      ]

# derived role
    - name: OrgViewer
      parentRoles: ['user']
      condition:
        match:
          any:
            of:
              - expr: P.attr.orgs[R.id].role == "owner"
              - expr: P.attr.orgs[R.attr.org_id].role == "owner"
              - expr: P.attr.orgs[R.id].role == "viewer"
              - expr: P.attr.orgs[R.attr.org_id].role == "viewer"

When I run is_allowed with the following principal and resource, things work as expected and shows that Cerbos is running and knows about the policies.

# principal
{
  "id": "user_764c63",
  "roles": ["user"],
  "attr": {"orgs": {"org_dd60a6": {"role": "owner"}}}
}

# resource
{
  "kind": "org",
  "id": "org_dd60a6",
  "attr": {
    "org_id": "org_dd60a6"
  }
}

c.is_allowed('org.read', principal, resource) # ---> True

When I try to run get_query with the above principal and the following code, it errors on the get_query line.

plan_resource = PlanResourcesInput.Resource(kind="org")
plan = c.plan_resources("org.read", p, plan_resource)
query = get_query(plan, models.Org, {"request.resource.id": models.Org._id})

The plan looks like this:

Printout of query plan
request_id: "84523808-6920-4e54-bbc7-0ee54d99de6b"
action: "org.read"
resource_kind: "org"
filter {
  kind: KIND_CONDITIONAL
  condition {
    expression {
      operator: "or"
      operands {
        expression {
          operator: "eq"
          operands {
            expression {
              operator: "get-field"
              operands {
                expression {
                  operator: "index"
                  operands {
                    expression {
                      operator: "struct"
                      operands {
                        expression {
                          operator: "set-field"
                          operands {
                            value {
                              string_value: "org_018e5806b4211f0fd2196c1644dd60a6"
                            }
                          }
                          operands {
                            expression {
                              operator: "struct"
                              operands {
                                expression {
                                  operator: "set-field"
                                  operands {
                                    value {
                                      string_value: "role"
                                    }
                                  }
                                  operands {
                                    value {
                                      string_value: "owner"
                                    }
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                  operands {
                    variable: "request.resource.id"
                  }
                }
              }
              operands {
                variable: "role"
              }
            }
          }
          operands {
            value {
              string_value: "owner"
            }
          }
        }
      }
      operands {
        expression {
          operator: "eq"
          operands {
            expression {
              operator: "get-field"
              operands {
                expression {
                  operator: "index"
                  operands {
                    expression {
                      operator: "struct"
                      operands {
                        expression {
                          operator: "set-field"
                          operands {
                            value {
                              string_value: "org_018e5806b4211f0fd2196c1644dd60a6"
                            }
                          }
                          operands {
                            expression {
                              operator: "struct"
                              operands {
                                expression {
                                  operator: "set-field"
                                  operands {
                                    value {
                                      string_value: "role"
                                    }
                                  }
                                  operands {
                                    value {
                                      string_value: "owner"
                                    }
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                  operands {
                    variable: "request.resource.attr.org_id"
                  }
                }
              }
              operands {
                variable: "role"
              }
            }
          }
          operands {
            value {
              string_value: "owner"
            }
          }
        }
      }
      operands {
        expression {
          operator: "eq"
          operands {
            expression {
              operator: "get-field"
              operands {
                expression {
                  operator: "index"
                  operands {
                    expression {
                      operator: "struct"
                      operands {
                        expression {
                          operator: "set-field"
                          operands {
                            value {
                              string_value: "org_018e5806b4211f0fd2196c1644dd60a6"
                            }
                          }
                          operands {
                            expression {
                              operator: "struct"
                              operands {
                                expression {
                                  operator: "set-field"
                                  operands {
                                    value {
                                      string_value: "role"
                                    }
                                  }
                                  operands {
                                    value {
                                      string_value: "owner"
                                    }
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                  operands {
                    variable: "request.resource.id"
                  }
                }
              }
              operands {
                variable: "role"
              }
            }
          }
          operands {
            value {
              string_value: "viewer"
            }
          }
        }
      }
      operands {
        expression {
          operator: "eq"
          operands {
            expression {
              operator: "get-field"
              operands {
                expression {
                  operator: "index"
                  operands {
                    expression {
                      operator: "struct"
                      operands {
                        expression {
                          operator: "set-field"
                          operands {
                            value {
                              string_value: "org_018e5806b4211f0fd2196c1644dd60a6"
                            }
                          }
                          operands {
                            expression {
                              operator: "struct"
                              operands {
                                expression {
                                  operator: "set-field"
                                  operands {
                                    value {
                                      string_value: "role"
                                    }
                                  }
                                  operands {
                                    value {
                                      string_value: "owner"
                                    }
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                  operands {
                    variable: "request.resource.attr.org_id"
                  }
                }
              }
              operands {
                variable: "role"
              }
            }
          }
          operands {
            value {
              string_value: "viewer"
            }
          }
        }
      }
    }
  }
}
cerbos_call_id: "01HSC29G47ZD606S6K6MHCVBG6"

The error is

File "/Users/foo/projects/my_project/api/.venv/lib/python3.11/site-packages/cerbos_sqlalchemy/query.py", line 127, in traverse_and_map_operands
    variable = d["variable"]
               ~^^^^^^^^^^^^
KeyError: 'variable'

When I put a print in the file where the error originates, I get this for the value of d:

{'expression': {'operator': 'get-field', 'operands': [{'expression': {'operator': 'index', 'operands': [{'expression': {'operator': 'struct', 'operands': [{'expression': {'operator': 'set-field', 'operands': [{'value': 'org_018e5806b4211f0fd2196c1644dd60a6'}, {'expression': {'operator': 'struct', 'operands': [{'expression': {'operator': 'set-field', 'operands': [{'value': 'role'}, {'value': 'owner'}]}}]}}]}}]}}, {'variable': 'request.resource.id'}]}}, {'variable': 'role'}]}, 'value': 'owner'}

There is no top level variable key in this data structure, which is why it throws an error. I don't really understand why the data structure d is wrong at this point though. Could someone help me out? Thanks!

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions