Tests
Topaz makes it easy to define and run a set of test cases known as assertions, to help test the model and prove that it authorizes correctly.
Defining assertions
Assertions are managed in a JSON file, by default named assertions.json
.
There are two types of assertions:
- Directory assertions, or
check
: define a test case that checks whether arelation
(or permission) exists between an object (identified byobject_type
andobject_id
) and a subject (identified bysubject_type
,subject_id
, and optionallysubject_relation
). - Authorizer assertions, or
check_decision
: define a test case that executes the authorizeris
API over the givenidentity_context
,resource_context
, andpolicy_context
Both types of assertions also include an expected
key, which can be either true
or false
depending on whether the assertion is supposed to succeed or fail.
The check_relation
and check_permission
are shown for backward-compatibility but are no longer used.
Directory assertions
topaz directory test template
emits a skeleton assertions file to stdout.
Example:
topaz directory test template
{
"assertions": [
{"check": {"object_type": "", "object_id": "", "relation": "", "subject_type": "", "subject_id": ""}, "expected": true},
{"check_relation": {"object_type": "", "object_id": "", "relation": "", "subject_type": "", "subject_id": ""}, "expected": true},
{"check_permission": {"object_type": "", "object_id": "", "permission": "", "subject_type": "", "subject_id": ""}, "expected": true},
]
}
You should only use the check
assertions. The check_relation
and check_permission
assertinos will be removed in a future release.
Authorizer assertions
topaz authorizer test template
emits a skeleton authorizer assertions file to stdout.
Example:
topaz authorizer test template
{
"assertions": [
{"check_decision": {"identity_context": {"identity": "", "type": ""}, "resource_context": {}, "policy_context": {"path": "", "decisions": [""]}}, "expected":true},
]
}
Running assertions
Directory assertions
topaz directory test exec
executes the assertions in a JSON file of the proper format, defaulting to ./assertions.json
. To specify a different file name, use the filename argument.
Example:
- Create the following
assertions.json
file, which defines a set of test cases for the data in thetodo
template:
{
"assertions": [
{
"check": {
"subject_type": "user",
"subject_id": "rick@the-citadel.com",
"relation": "member",
"object_type": "group",
"object_id": "admin"
},
"expected": true
},
{
"check": {
"subject_type": "user",
"subject_id": "rick@the-citadel.com",
"relation": "member",
"object_type": "group",
"object_id": "evil_genius"
},
"expected": true
},
{
"check": {
"subject_type": "user",
"subject_id": "rick@the-citadel.com",
"relation": "member",
"object_type": "group",
"object_id": "editor"
},
"expected": false
},
{
"check": {
"subject_type": "user",
"subject_id": "rick@the-citadel.com",
"relation": "member",
"object_type": "group",
"object_id": "viewer"
},
"expected": false
},
{
"check": {
"subject_type": "user",
"subject_id": "morty@the-citadel.com",
"relation": "member",
"object_type": "group",
"object_id": "admin"
},
"expected": false
},
{
"check": {
"subject_type": "user",
"subject_id": "morty@the-citadel.com",
"relation": "member",
"object_type": "group",
"object_id": "evil_genius"
},
"expected": false
},
{
"check": {
"subject_type": "user",
"subject_id": "morty@the-citadel.com",
"relation": "member",
"object_type": "group",
"object_id": "editor"
},
"expected": true
},
{
"check": {
"subject_type": "user",
"subject_id": "morty@the-citadel.com",
"relation": "member",
"object_type": "group",
"object_id": "viewer"
},
"expected": false
},
{
"check": {
"subject_type": "user",
"subject_id": "summer@the-smiths.com",
"relation": "member",
"object_type": "group",
"object_id": "admin"
},
"expected": false
},
{
"check": {
"subject_type": "user",
"subject_id": "summer@the-smiths.com",
"relation": "member",
"object_type": "group",
"object_id": "evil_genius"
},
"expected": false
},
{
"check": {
"subject_type": "user",
"subject_id": "summer@the-smiths.com",
"relation": "member",
"object_type": "group",
"object_id": "editor"
},
"expected": true
},
{
"check": {
"subject_type": "user",
"subject_id": "summer@the-smiths.com",
"relation": "member",
"object_type": "group",
"object_id": "viewer"
},
"expected": false
},
{
"check": {
"subject_type": "user",
"subject_id": "beth@the-smiths.com",
"relation": "member",
"object_type": "group",
"object_id": "admin"
},
"expected": false
},
{
"check": {
"subject_type": "user",
"subject_id": "beth@the-smiths.com",
"relation": "member",
"object_type": "group",
"object_id": "evil_genius"
},
"expected": false
},
{
"check": {
"subject_type": "user",
"subject_id": "beth@the-smiths.com",
"relation": "member",
"object_type": "group",
"object_id": "editor"
},
"expected": false
},
{
"check": {
"subject_type": "user",
"subject_id": "beth@the-smiths.com",
"relation": "member",
"object_type": "group",
"object_id": "viewer"
},
"expected": true
},
{
"check": {
"subject_type": "user",
"subject_id": "jerry@the-smiths.com",
"relation": "member",
"object_type": "group",
"object_id": "admin"
},
"expected": false
},
{
"check": {
"subject_type": "user",
"subject_id": "jerry@the-smiths.com",
"relation": "member",
"object_type": "group",
"object_id": "evil_genius"
},
"expected": false
},
{
"check": {
"subject_type": "user",
"subject_id": "jerry@the-smiths.com",
"relation": "member",
"object_type": "group",
"object_id": "editor"
},
"expected": false
},
{
"check": {
"subject_type": "user",
"subject_id": "jerry@the-smiths.com",
"relation": "member",
"object_type": "group",
"object_id": "viewer"
},
"expected": true
}
]
}
- Run the test suite:
topaz directory test exec -i
0001 check PASS group:admin#member@user:rick@the-citadel.com [true] (2.764667ms)
0002 check PASS group:evil_genius#member@user:rick@the-citadel.com [true] (1.545541ms)
0003 check PASS group:editor#member@user:rick@the-citadel.com [false] (1.665166ms)
0004 check PASS group:viewer#member@user:rick@the-citadel.com [false] (1.583125ms)
0005 check PASS group:admin#member@user:morty@the-citadel.com [false] (1.369542ms)
0006 check PASS group:evil_genius#member@user:morty@the-citadel.com [false] (1.399875ms)
0007 check PASS group:editor#member@user:morty@the-citadel.com [true] (1.297292ms)
0008 check PASS group:viewer#member@user:morty@the-citadel.com [false] (1.375917ms)
0009 check PASS group:admin#member@user:summer@the-smiths.com [false] (1.498042ms)
0010 check PASS group:evil_genius#member@user:summer@the-smiths.com [false] (1.34ms)
0011 check PASS group:editor#member@user:summer@the-smiths.com [true] (1.349875ms)
0012 check PASS group:viewer#member@user:summer@the-smiths.com [false] (1.328584ms)
0013 check PASS group:admin#member@user:beth@the-smiths.com [false] (1.364667ms)
0014 check PASS group:evil_genius#member@user:beth@the-smiths.com [false] (1.412834ms)
0015 check PASS group:editor#member@user:beth@the-smiths.com [false] (1.781375ms)
0016 check PASS group:viewer#member@user:beth@the-smiths.com [true] (1.782375ms)
0017 check PASS group:admin#member@user:jerry@the-smiths.com [false] (1.790791ms)
0018 check PASS group:evil_genius#member@user:jerry@the-smiths.com [false] (1.44825ms)
0019 check PASS group:editor#member@user:jerry@the-smiths.com [false] (1.366709ms)
0020 check PASS group:viewer#member@user:jerry@the-smiths.com [true] (1.349167ms)
Authorizer assertions
topaz authorizer test exec
executes the assertions in a JSON file of the proper format, defaulting to ./assertions.json
. To specify a different file name, use the filename argument.
Example:
- Create the following
assertions.json
file, which defines a set of test cases for the data in thetodo
template:
{
"assertions": [
{
"check_decision": {
"identity_context": { "identity": "rick@the-citadel.com", "type": "IDENTITY_TYPE_SUB" },
"resource_context": {},
"policy_context": { "path": "todoApp.GET.todos", "decisions": ["allowed"] }
},
"expected": true
},
{
"check_decision": {
"identity_context": { "identity": "morty@the-citadel.com", "type": "IDENTITY_TYPE_SUB" },
"resource_context": { "object_type": "resource-creator", "object_id": "resource-creators", "relation": "member" },
"policy_context": { "path": "todoApp.POST.todos", "decisions": ["allowed"] }
},
"expected": true
},
{
"check_decision": {
"identity_context": { "identity": "jerry@the-smiths.com", "type": "IDENTITY_TYPE_SUB" },
"resource_context": {},
"policy_context": { "path": "todoApp.GET.todos", "decisions": ["allowed"] }
},
"expected": true
},
{
"check_decision": {
"identity_context": { "identity": "jerry@the-smiths.com", "type": "IDENTITY_TYPE_SUB" },
"resource_context": { "object_type": "resource-creator", "object_id": "resource-creators", "relation": "member" },
"policy_context": { "path": "todoApp.POST.todos", "decisions": ["allowed"] }
},
"expected": false
}
]
}
- Run the test suite:
topaz authorizer test exec -i
0001 check_decision PASS todoApp.GET.todos/allowed:rick@the-citadel.com [true] (65.22175ms)
0002 check_decision PASS todoApp.POST.todos/allowed:morty@the-citadel.com [true] (3.702959ms)
0003 check_decision PASS todoApp.GET.todos/allowed:jerry@the-smiths.com [true] (2.012125ms)
0004 check_decision PASS todoApp.POST.todos/allowed:jerry@the-smiths.com [false] (2.7505ms)