hello! :wave: I'm looking for some help with my C...
# help
b
hello! 👋 I'm looking for some help with my Cerbos policies. up until now, our current approach has been working fine. however, I now need to restrict users from sharing workflows 1) if their org limits sharing to Admins (so Members cannot share) and 2) externally if their org limits sharing to internal-only. for #1, my first thought is to create a new
workflow_sharer
derived role that's separate from
workflow_owner
. while I think this would work, I'm wondering if this is a sign that our current approach is not going to be the best approach for us in the future if we continue to need new granular access controls based on things like org settings. for #2, it seems like it would make sense that our product simply doesn't allow users of an org with external sharing disabled to set
publicRole
at all. it makes sense to me that this doesn't need to be a policy-level catch. does that make sense? I've included parts of our resource and role files in the thread.
Copy code
apiVersion: api.cerbos.dev/v1
resourcePolicy:
  version: default
  resource: workflow
  importDerivedRoles:
    - workflow_derived_roles
  rules:
    - derivedRoles: ["workflow_owner"]
      actions:
        ["DELETE_WORKFLOW", "EDIT_WORKFLOW", "SHARE_WORKFLOW"]
      effect: EFFECT_ALLOW

    - derivedRoles: ["workflow_editor"]
      actions: ["EDIT_WORKFLOW"]
      effect: EFFECT_ALLOW
Copy code
apiVersion: api.cerbos.dev/v1
derivedRoles:
  name: workflow_derived_roles
  variables:
    import:
      - common_variables
    local:
      workflowCreatorOrgId: R.attr.creator.orgId
      workflowPublicRole: R.attr.publicRole
      workflowOrgRole: R.attr.orgRole
      userRoles: P.attr.userRoles
  definitions:
    - name: workflow_owner
      parentRoles: ["user"]
      condition:
        match:
          any:
            of:
              # publicRole is set to OWNER
              - expr: V.workflowPublicRole == V.WORKFLOW_ROLE_OWNER
              # User is the creator of the workflow
              - expr: P.id == R.attr.creator.id
              # User is in the same org as the workflow creator and orgRole is set to OWNER
              - expr: >
                  P.attr.orgId == V.workflowCreatorOrgId
                  && V.workflowOrgRole == V.WORKFLOW_ROLE_OWNER
              # User has OWNER WorkflowUserRole
              - expr: >
                  V.userRoles.exists(userRole,
                    userRole.role == V.WORKFLOW_ROLE_OWNER && userRole.workflowId == R.id
                  )

    - name: workflow_editor
      parentRoles: ["user"]
      condition:
        match:
          any:
            of:
              # publicRole is set to EDITOR
              - expr: V.workflowPublicRole == V.WORKFLOW_ROLE_EDITOR
              # User is in the same org as the workflow creator and orgRole is set to EDITOR
              - expr: >
                  P.attr.orgId == V.workflowCreatorOrgId
                  && V.workflowOrgRole == V.WORKFLOW_ROLE_EDITOR
              # User has EDITOR WorkflowUserRole
              - expr: >
                  V.userRoles.exists(userRole,
                    userRole.role == V.WORKFLOW_ROLE_EDITOR && userRole.workflowId == R.id
                  )
a
For #1, I would probably model that as two separate rules in the resource policy. You could do it with an allow and a deny: allow workflow owners to share unconditionally, then deny non-admins sharing conditionally based on the org setting (which you'd pass in as a resource attribute). Deny rules take precedence over allows. For #2, yeah, you could enforce this elsewhere, but it does sound a lot like a policy, so it might make sense to model it in Cerbos.
b
hi andrew. thanks for getting back to me! could you explain why the org setting would be a resource attribute as opposed to a principal attribute? org settings seem to me like an attribute of the org that a user is in, not an attribute of the workflow. I suppose it wouldn't change the actual authorization, but I am curious. I'll see what I can come up with for #2
a
Oh right, yeah, there's no reason it can't be a principal attribute if that makes sense for your data model. I would make it a resource attribute if workflows belong to orgs and users can belong to more than one org, but if a user belongs to one org then a principal attribute would be fine too!