shackra
shackra

Reputation: 366

how do I check an array of objects in REGO to check if a user has permissions conceit?

I'm trying to check if a user have certain permission conceit given a subject and action to check against, sadly I'm unable to make it work, this is the REGO file:

package monolith.tiene_permiso

default permitir = false

permitir {
    es_admin
}

permitir {
    # Find grants for the user.
    some grant
    usuario_tiene_permitido[grant]

    # Check if the grant permits the action.
    input.permiso.accion == grant.accion
    input.permiso.sujeto == grant.sujeto
}

es_admin {
    some key
    input.permisos[_][key]
    key == data.admin_name
}

usuario_tiene_permitido[accion] {
    some j

    accion := input.permisos[_][input.permiso.sujeto][j]
}

And this is the unit test, this reflects how the inputs are provided from the Go code:

package monolith.tiene_permiso

admin_name = {"admin_name": "admin"}

test_permiso_autorizado {
    permitir with input as {
        "permiso": {"sujeto": "x", "accion": "a"},
        "permisos": [{"x": ["a"]}],
    }
         with data.admin_name as admin_name
}

And well, this is the result:

FAILURES
--------------------------------------------------------------------------------
data.monolith.tiene_permiso.test_permiso_autorizado: FAIL (293.209µs)

  query:1                        Enter data.monolith.tiene_permiso.test_permiso_autorizado = _
  query:1                        | Eval data.monolith.tiene_permiso.test_permiso_autorizado = _
  query:1                        | Index data.monolith.tiene_permiso.test_permiso_autorizado = _ (matched 1 rule)
  tiene_permiso_test.rego:5      | Enter data.monolith.tiene_permiso.test_permiso_autorizado
  tiene_permiso_test.rego:10     | | Eval __local3__ = data.monolith.tiene_permiso.admin_name
  tiene_permiso_test.rego:10     | | Index __local3__ = data.monolith.tiene_permiso.admin_name (matched 1 rule)
  tiene_permiso_test.rego:3      | | Enter data.monolith.tiene_permiso.admin_name
  tiene_permiso_test.rego:3      | | | Eval true
  tiene_permiso_test.rego:3      | | | Exit data.monolith.tiene_permiso.admin_name
  tiene_permiso_test.rego:6      | | Eval data.monolith.tiene_permiso.permitir with input as {"permiso": {"accion": "a", "sujeto": "x"}, "permisos": [{"x": ["a"]}]} with data.admin_name as __local3__
  tiene_permiso_test.rego:6      | | Index data.monolith.tiene_permiso.permitir with input as {"permiso": {"accion": "a", "sujeto": "x"}, "permisos": [{"x": ["a"]}]} with data.admin_name as __local3__ matched 2 rules)
  tiene_permiso.rego:5           | | Enter data.monolith.tiene_permiso.permitir
  tiene_permiso.rego:6           | | | Eval data.monolith.tiene_permiso.es_admin
  tiene_permiso.rego:6           | | | Index data.monolith.tiene_permiso.es_admin (matched 1 rule)
  tiene_permiso.rego:19          | | | Enter data.monolith.tiene_permiso.es_admin
  tiene_permiso.rego:20          | | | | Eval input.permisos[_][key] = data.admin_name
  tiene_permiso.rego:20          | | | | Fail input.permisos[_][key] = data.admin_name
  tiene_permiso.rego:6           | | | Fail data.monolith.tiene_permiso.es_admin
  tiene_permiso.rego:9           | | Enter data.monolith.tiene_permiso.permitir
  tiene_permiso.rego:12          | | | Eval data.monolith.tiene_permiso.usuario_tiene_permitido[grant]
  tiene_permiso.rego:12          | | | Index data.monolith.tiene_permiso.usuario_tiene_permitido[__local0__] (matched 1 rule)
  tiene_permiso.rego:23          | | | Enter data.monolith.tiene_permiso.usuario_tiene_permitido
  tiene_permiso.rego:26          | | | | Eval __local4__ = input.permiso.sujeto
  tiene_permiso.rego:26          | | | | Eval accion = input.permisos[_][__local4__][j]
  tiene_permiso.rego:23          | | | | Exit data.monolith.tiene_permiso.usuario_tiene_permitido
  tiene_permiso.rego:15          | | | Eval input.permiso.accion = grant.accion
  tiene_permiso.rego:15          | | | Fail input.permiso.accion = grant.accion
  tiene_permiso.rego:12          | | | Redo data.monolith.tiene_permiso.usuario_tiene_permitido[grant]
  tiene_permiso.rego:23          | | | Redo data.monolith.tiene_permiso.usuario_tiene_permitido
  tiene_permiso.rego:26          | | | | Redo accion = input.permisos[_][__local4__][j]
  tiene_permiso.rego:26          | | | | Redo __local4__ = input.permiso.sujeto
  tiene_permiso.rego:3           | | Enter data.monolith.tiene_permiso.permitir
  tiene_permiso.rego:3           | | | Eval true
  tiene_permiso.rego:3           | | | Exit data.monolith.tiene_permiso.permitir
  tiene_permiso.rego:3           | | Redo data.monolith.tiene_permiso.permitir
  tiene_permiso.rego:3           | | | Redo true
  tiene_permiso_test.rego:6      | | Fail data.monolith.tiene_permiso.permitir with input as {"permiso": {"accion": "a", "sujeto": "x"}, "permisos": [{"x": ["a"]}]} with data.admin_name as __local3__
  tiene_permiso_test.rego:10     | | Redo __local3__ = data.monolith.tiene_permiso.admin_name
  tiene_permiso_test.rego:3      | | Redo data.monolith.tiene_permiso.admin_name
  tiene_permiso_test.rego:3      | | | Redo true
  query:1                        | Fail data.monolith.tiene_permiso.test_permiso_autorizado = _

SUMMARY
--------------------------------------------------------------------------------
data.monolith.tiene_permiso.test_permiso_autorizado: FAIL (293.209µs)
--------------------------------------------------------------------------------
FAIL: 1/1

What am I doing wrong? And how do I change my code to achieve what I need?

Upvotes: 0

Views: 598

Answers (1)

tsandall
tsandall

Reputation: 1609

The permitir rule is failing on this line:

input.permiso.accion == grant.accion

The trace reports this (albeit with a lot of other noise):

  tiene_permiso.rego:15          | | | Eval input.permiso.accion = grant.accion
  tiene_permiso.rego:15          | | | Fail input.permiso.accion = grant.accion

The reason it's failing is that usuario_tiene_permitido generates a set of actions represented as strings, i.e., grant is a string not an object containing the subject and action. If you evaluate usuario_tiene_permitido with the input you provided, you'll see this.

You could refactor the permitir rule as follows:

permitir {
    # Find grants for the user.
    some grant
    usuario_tiene_permitido[grant]
    input.permiso.accion == grant
}

Upvotes: 1

Related Questions