# Thumper Thumper is a traffic generator for SpiceDB and Authzed. It will issue CheckPermission, Read/Write Relationships, ExpandPermissionTree and LookupResources to a SpiceDB or Authzed endpoint, and exposes Prometheus metrics about those operations. Thumper is currently private. Reach out to the Authzed team by emailing support@authzed.com if you are interested in using it. ## Setting up Run the migration script required by your thumper scripts against your permission system. ```sh thumper migrate --endpoint grpc.authzed.com:443 --token t_some_token --insecure false ./scripts/schema.yaml ``` ## Running ### Running against an Authzed instance ```sh thumper run --endpoint grpc.authzed.com:443 --token t_some_token --insecure false ./scripts/example.yaml ``` ### Running against a local SpiceDB ```sh thumper run --token presharedkeyhere ./scripts/example.yaml ``` ## Configuring ### Changing the QPS By default, Thumper will run a single goroutine, which will issues calls once per second, at rates configured in [thumperrunner/definitions.go](thumperrunner/definitions.go). To increase the number of calls issued, the `THUMPER_QPS` environment variable or `--qps` flag can be used: ```sh thumper run --token presharedkeyhere --qps 5 ``` The above will spawn 5 goroutines, which will each issue calls once per second. ### Script Format Thumper config files are yaml files with go template preprocessing supported. The final yaml generated by the templates must validate with the schema in `config/schema.yaml`. #### Example ```yaml name: create org, tenant, and add client weight: 1 steps: - op: CheckPermission resource: {{ .Prefix }}tenant:ps_{{ randomObjectID }} subject: {{ .Prefix }}token:t_{{ randomObjectID }} permission: write_relationships expectNoPermission: true consistency: AtLeastAsFresh - op: LookupResources resource: {{ .Prefix }}tenant permission: view_tenant subject: {{ .Prefix }}token:t_{{ randomObjectID }} numExpected: 0 consistency: AtLeastAsFresh - op: WriteRelationships updates: - op: TOUCH resource: {{ .Prefix }}organization:org_{{ randomObjectID }} subject: {{ .Prefix }}platform:plat_{{ randomObjectID }} relation: platform - op: TOUCH resource: {{ .Prefix }}tenant:ps_{{ randomObjectID }} subject: {{ .Prefix }}organization:org_{{ randomObjectID }} relation: organization - op: TOUCH resource: {{ .Prefix }}tenant:ps_{{ randomObjectID }} subject: {{ .Prefix }}client:client_{{ randomObjectID }}#token relation: writer - op: TOUCH resource: {{ .Prefix }}client:client_{{ randomObjectID }} subject: {{ .Prefix }}token:t_{{ randomObjectID }} relation: token - op: CheckPermission resource: {{ .Prefix }}tenant:ps_{{ randomObjectID }} subject: {{ .Prefix }}token:t_{{ randomObjectID }} permission: write_relationships consistency: AtLeastAsFresh - op: LookupResources resource: {{ .Prefix }}tenant permission: view_tenant subject: {{ .Prefix }}token:t_{{ randomObjectID }} numExpected: 1 consistency: AtLeastAsFresh - op: WriteRelationships updates: - op: DELETE resource: {{ .Prefix }}organization:org_{{ randomObjectID }} subject: {{ .Prefix }}platform:plat_{{ randomObjectID }} relation: platform - op: DELETE resource: {{ .Prefix }}tenant:ps_{{ randomObjectID }} subject: {{ .Prefix }}organization:org_{{ randomObjectID }} relation: organization - op: DELETE resource: {{ .Prefix }}tenant:ps_{{ randomObjectID }} subject: {{ .Prefix }}client:client_{{ randomObjectID }}#token relation: writer - op: DELETE resource: {{ .Prefix }}client:client_{{ randomObjectID }} subject: {{ .Prefix }}token:t_{{ randomObjectID }} relation: token - op: LookupResources resource: {{ .Prefix }}tenant permission: view_tenant subject: {{ .Prefix }}token:t_{{ randomObjectID }} numExpected: 0 consistency: AtLeastAsFresh - op: CheckPermission resource: {{ .Prefix }}tenant:ps_{{ randomObjectID }} subject: {{ .Prefix }}token:t_{{ randomObjectID }} permission: write_relationships expectNoPermission: true consistency: AtLeastAsFresh ``` #### Types The following common types are used in various operations: | Type | Example(s) | Used In | | ---- | ---------- | ------- | | Permission/Relation Name | reader, writer, view | * | | Object Reference | objecttype:objectid | CheckPermission, ExpandPermissionTree, LookupSubjects, WriteRelationships | | Subject Reference | subjecttype:subjectid, subjecttype:subjectid#optionalrelation | CheckPermission, ReadRelationships, DeleteRelationships, ExpandPermissionTree, WriteRelationships | | Object Type | objecttype | LookupResources, LookupSubjects | | Object Filter | objecttype, objecttype:objectid | ReadRelationships, DeleteRelationships | #### Go Template Properties The following properties are available to be used from within go templates: ##### enumerate(length) This function will generate an array with the specific length filled with the natural numbers. This array can be ranged over to repeat a script fragment a number of times with a varying identifier. Example: ```yaml name: many checks steps: {{- range $i := enumerate 100 }} - op: CheckPermission resource: document:{{ $i }} subject: user:stacy permission: read {{- end }} ``` ##### randomObjectID This function returns a different random object ID per worker allowing many workers to work on the same flow in parallel. Example: ```yaml name: check permissions on random document weight: 1 steps: - op: WriteRelationships updates: - op: TOUCH resource: document:{{ randomObjectID }} subject: user:stacy relation: reader - op: CheckPermission resource: document:{{ randomObjectID }} subject: user:stacy permission: read ``` ##### Prefix This parameter contains the value of the `--prefix` command line parameter followed by a `/`, and can be used to isolate schemas and data between different instances of `thumper`. Example: ```yaml name: check permissions on random tenant weight: 1 steps: - op: WriteRelationships updates: - op: TOUCH resource: {{ .Prefix }}document:1 subject: {{ .Prefix }}user:stacy relation: reader - op: CheckPermission resource: {{ .Prefix }}document:1 subject: {{ .Prefix }}user:stacy permission: read ``` ##### IsMigration This parameter contains a boolean that specifies whether the script is being run under the `thumper migrate` command. This can be used to write a script that contains both a migration and the actual test scripts. Example: ```yaml {{- if .IsMigration }} --- name: write schema steps: - op: WriteSchema schema: | definition user {} definition document { relation reader: user } - op: WriteRelationships updates: - op: TOUCH resource: document:1 subject: user:stacy relation: reader {{- else }} --- name: check permissions weight: 1 steps: - op: CheckPermission resource: document:1 subject: user:stacy permission: reader {{- end }} ```