Skip to content

feat(assignment): add OpenFGA assignment driver - #1206

Merged
gtema merged 1 commit into
mainfrom
openfga
Sep 4, 2026
Merged

gtema merged 1 commit into
mainfrom
openfga

Conversation

@gtema

@gtema gtema commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

Keystone role assignments are a relationship graph; OpenFGA models that
natively, letting deployments that already run it as their central authz
store put OpenStack and non-OpenStack resources under one model with
group/implication resolution done once, not per-consumer.

  • Config-only entity<->object mapping (crates/config), no new
    Keystone-side mapping table
  • listing shapes this driver structurally cannot answer (no actor and no
    target, or role-only) return 501 via a new
    AssignmentProviderError::NotImplement, not backend faults
  • object enumeration uses streamed-list-objects instead of list-objects
    to avoid its silent 1000-result truncation
  • bounded concurrency (max_concurrency, default 10) on every fan-out
    over actor/target representations and role relations
  • retry with exponential backoff on 429/5xx/transient transport errors

See doc/src/adr/0033-openfga-assignment-driver.md, including the
Negative consequences: this driver does not sync Keystone group
membership into OpenFGA, so effective-mode token issuance needs that
pipeline built externally before switching drivers.

Signed-off-by: Artem Goncharov artem.goncharov@gmail.com

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown

🦢 Load Test Results

Goose Attack Report

Plan Overview

Action Started Stopped Elapsed Users
Increasing 26-09-04 16:59:04 26-09-04 16:59:28 00:00:24 0 → 45
Maintaining 26-09-04 16:59:28 26-09-04 16:59:58 00:00:30 45
Decreasing 26-09-04 16:59:58 26-09-04 16:59:58 00:00:00 0 ← 45

Request Metrics

Method Name # Requests # Fails Average (ms) Min (ms) Max (ms) RPS Failures/s
DELETE DELETE /v3/auth/tokens 47 0 526.72 43 709 1.57 0.00
DELETE DELETE /v3/projects/:id (teardown) 1 0 168.00 168 168 0.03 0.00
DELETE DELETE /v3/roles/:id (teardown) 1 0 238.00 238 238 0.03 0.00
DELETE DELETE /v3/users/:id (teardown) 2 0 224.50 150 299 0.07 0.00
DELETE DELETE /v4/mappings/rulesets/:mapping_id (teardown) 1 0 143.00 143 143 0.03 0.00
DELETE DELETE /v4/oauth2/:domain_id/clients/:provider_id (teardown) 1 0 112.00 112 112 0.03 0.00
GET 644 0 547.69 339 820 21.47 0.00
GET GET /SCIM/v2/:domain_id/Users (sync reconcile list) 2043 2043 14.37 1 786 68.10 68.10
GET GET /v3/auth/tokens (validate new) 46 0 488.00 146 666 1.53 0.00
GET GET /v3/auth/tokens (validate revoked) 48 0 477.67 24 642 1.60 0.00
GET GET /v3/projects/:id 59 0 519.59 373 669 1.97 0.00
GET GET /v3/projects/:id (catalog) 88 0 523.08 356 691 2.93 0.00
GET GET /v3/role_assignments 45 0 520.20 358 641 1.50 0.00
GET GET /v3/role_assignments?role.id 46 0 515.04 315 657 1.53 0.00
GET GET /v3/role_assignments?scope.domain.id 45 0 489.47 325 679 1.50 0.00
GET GET /v3/role_assignments?user.id 46 0 484.20 365 615 1.53 0.00
GET GET /v3/roles 119 0 513.95 341 685 3.97 0.00
GET GET /v3/roles/:id 59 0 513.02 312 695 1.97 0.00
GET GET /v3/users/:id 112 0 542.33 360 718 3.73 0.00
GET GET /v3/users/:id (catalog) 112 0 535.04 370 706 3.73 0.00
GET GET /v4/api-keys 29 0 518.07 360 669 0.97 0.00
GET GET /v4/api-keys/:client_id 29 0 545.72 384 677 0.97 0.00
GET GET /v4/mappings/rulesets 30 0 528.70 370 737 1.00 0.00
GET GET /v4/mappings/rulesets/:mapping_id 30 0 497.00 346 668 1.00 0.00
GET GET /v4/oauth2/:domain_id/.well-known/openid-configuration 922 0 48.90 7 200 30.73 0.00
GET GET /v4/oauth2/:domain_id/clients 30 0 511.30 381 663 1.00 0.00
GET GET /v4/oauth2/:domain_id/clients/:provider_id 30 0 510.93 330 675 1.00 0.00
GET GET /v4/oauth2/:domain_id/jwks 921 0 48.43 9 173 30.70 0.00
GET GET /v4/scim_realms 19 0 505.11 378 606 0.63 0.00
GET GET /v4/scim_realms/:domain_id/:provider_id 19 0 533.47 351 674 0.63 0.00
POST POST /v3/auth/tokens 46 0 482.30 361 598 1.53 0.00
POST POST /v3/auth/tokens (password, invalid) 30 0 1048.07 595 1610 1.00 0.00
POST POST /v3/auth/tokens (password, project-scoped) 52 0 1300.87 788 2009 1.73 0.00
POST POST /v3/auth/tokens (password, unscoped) 53 0 1103.17 688 1784 1.77 0.00
POST POST /v3/auth/tokens (rescope to system) 106 0 577.96 389 732 3.53 0.00
POST POST /v3/auth/tokens (rescope, invalid project) 63 0 478.63 343 672 2.10 0.00
POST POST /v3/auth/tokens (system-scoped, bootstrap admin) 49 0 1282.43 755 1763 1.63 0.00
POST POST /v3/users (setup) 1 0 1751.00 1751 1751 0.03 0.00
POST POST /v4/api-keys/:client_id/revoke (teardown) 1 0 188.00 188 188 0.03 0.00
PUT PUT /v4/scim_realms/:domain_id/:provider_id 19 0 572.63 460 899 0.63 0.00
Aggregated 6044 2043 228.66 1 2009 201.47 68.10

Response Time Metrics

Method Name 50%ile (ms) 60%ile (ms) 70%ile (ms) 80%ile (ms) 90%ile (ms) 95%ile (ms) 99%ile (ms) 100%ile (ms)
DELETE DELETE /v3/auth/tokens 500 500 600 600 700 700 700 700
DELETE DELETE /v3/projects/:id (teardown) 168 168 168 168 168 168 168 168
DELETE DELETE /v3/roles/:id (teardown) 238 238 238 238 238 238 238 238
DELETE DELETE /v3/users/:id (teardown) 150 150 150 299 299 299 299 299
DELETE DELETE /v4/mappings/rulesets/:mapping_id (teardown) 143 143 143 143 143 143 143 143
DELETE DELETE /v4/oauth2/:domain_id/clients/:provider_id (teardown) 112 112 112 112 112 112 112 112
GET 500 600 600 600 700 700 800 800
GET GET /SCIM/v2/:domain_id/Users (sync reconcile list) 6 7 9 11 16 22 370 786
GET GET /v3/auth/tokens (validate new) 480 500 500 600 600 600 666 666
GET GET /v3/auth/tokens (validate revoked) 470 500 500 600 600 600 600 600
GET GET /v3/projects/:id 500 500 600 600 600 600 600 669
GET GET /v3/projects/:id (catalog) 500 500 600 600 600 600 691 691
GET GET /v3/role_assignments 500 500 600 600 600 600 600 600
GET GET /v3/role_assignments?role.id 500 500 600 600 600 600 657 657
GET GET /v3/role_assignments?scope.domain.id 490 500 500 600 600 600 679 679
GET GET /v3/role_assignments?user.id 480 500 500 500 600 600 600 600
GET GET /v3/roles 500 500 500 600 600 600 685 685
GET GET /v3/roles/:id 500 500 500 600 600 600 695 695
GET GET /v3/users/:id 500 600 600 600 600 700 700 700
GET GET /v3/users/:id (catalog) 500 500 600 600 600 700 700 700
GET GET /v4/api-keys 500 500 600 600 600 669 669 669
GET GET /v4/api-keys/:client_id 600 600 600 600 600 677 677 677
GET GET /v4/mappings/rulesets 500 600 600 600 600 700 700 700
GET GET /v4/mappings/rulesets/:mapping_id 490 500 500 600 600 600 668 668
GET GET /v4/oauth2/:domain_id/.well-known/openid-configuration 42 50 58 68 81 100 130 200
GET GET /v4/oauth2/:domain_id/clients 500 500 600 600 600 663 663 663
GET GET /v4/oauth2/:domain_id/clients/:provider_id 500 500 600 600 600 675 675 675
GET GET /v4/oauth2/:domain_id/jwks 41 48 57 68 83 100 130 170
GET GET /v4/scim_realms 500 500 500 600 600 600 600 600
GET GET /v4/scim_realms/:domain_id/:provider_id 500 500 600 600 674 674 674 674
POST POST /v3/auth/tokens 480 500 500 500 598 598 598 598
POST POST /v3/auth/tokens (password, invalid) 1,000 1,000 1,000 1,000 1,000 1,000 1,610 1,610
POST POST /v3/auth/tokens (password, project-scoped) 1,000 1,000 1,000 1,000 2,000 2,000 2,000 2,000
POST POST /v3/auth/tokens (password, unscoped) 1,000 1,000 1,000 1,000 1,000 1,784 1,784 1,784
POST POST /v3/auth/tokens (rescope to system) 600 600 600 600 700 700 700 700
POST POST /v3/auth/tokens (rescope, invalid project) 460 490 500 500 600 600 600 672
POST POST /v3/auth/tokens (system-scoped, bootstrap admin) 1,000 1,000 1,000 1,000 1,763 1,763 1,763 1,763
POST POST /v3/users (setup) 1,751 1,751 1,751 1,751 1,751 1,751 1,751 1,751
POST POST /v4/api-keys/:client_id/revoke (teardown) 188 188 188 188 188 188 188 188
PUT PUT /v4/scim_realms/:domain_id/:provider_id 600 600 600 600 700 700 899 899
Aggregated 45 78 450 500 600 700 1,000 2,000

Status Code Metrics

Method Name Status Codes
DELETE DELETE /v3/auth/tokens 47 [204]
DELETE DELETE /v3/projects/:id (teardown) 1 [204]
DELETE DELETE /v3/roles/:id (teardown) 1 [204]
DELETE DELETE /v3/users/:id (teardown) 2 [204]
DELETE DELETE /v4/mappings/rulesets/:mapping_id (teardown) 1 [204]
DELETE DELETE /v4/oauth2/:domain_id/clients/:provider_id (teardown) 1 [204]
GET 644 [200]
GET GET /SCIM/v2/:domain_id/Users (sync reconcile list) 2,012 [429], 31 [401]
GET GET /v3/auth/tokens (validate new) 46 [200]
GET GET /v3/auth/tokens (validate revoked) 48 [404]
GET GET /v3/projects/:id 59 [200]
GET GET /v3/projects/:id (catalog) 88 [200]
GET GET /v3/role_assignments 45 [200]
GET GET /v3/role_assignments?role.id 46 [200]
GET GET /v3/role_assignments?scope.domain.id 45 [200]
GET GET /v3/role_assignments?user.id 46 [200]
GET GET /v3/roles 119 [200]
GET GET /v3/roles/:id 59 [200]
GET GET /v3/users/:id 112 [200]
GET GET /v3/users/:id (catalog) 112 [200]
GET GET /v4/api-keys 29 [200]
GET GET /v4/api-keys/:client_id 29 [200]
GET GET /v4/mappings/rulesets 30 [200]
GET GET /v4/mappings/rulesets/:mapping_id 30 [200]
GET GET /v4/oauth2/:domain_id/.well-known/openid-configuration 922 [200]
GET GET /v4/oauth2/:domain_id/clients 30 [200]
GET GET /v4/oauth2/:domain_id/clients/:provider_id 30 [200]
GET GET /v4/oauth2/:domain_id/jwks 921 [200]
GET GET /v4/scim_realms 19 [200]
GET GET /v4/scim_realms/:domain_id/:provider_id 19 [200]
POST POST /v3/auth/tokens 46 [201]
POST POST /v3/auth/tokens (password, invalid) 30 [401]
POST POST /v3/auth/tokens (password, project-scoped) 52 [201]
POST POST /v3/auth/tokens (password, unscoped) 53 [201]
POST POST /v3/auth/tokens (rescope to system) 106 [201]
POST POST /v3/auth/tokens (rescope, invalid project) 63 [401]
POST POST /v3/auth/tokens (system-scoped, bootstrap admin) 49 [201]
POST POST /v3/users (setup) 1 [201]
POST POST /v4/api-keys/:client_id/revoke (teardown) 1 [200]
PUT PUT /v4/scim_realms/:domain_id/:provider_id 19 [200]
Aggregated 3,500 [200], 2,012 [429], 48 [404], 53 [204], 124 [401], 307 [201]

Transaction Metrics

Transaction # Times Run # Fails Average (ms) Min (ms) Max (ms) RPS Failures/s
ReadHeavy
0.0 1 0 44.00 44 44 0.03 0.00
0.1 116 0 547.25 374 792 3.87 0.00
0.2 114 0 531.86 377 708 3.80 0.00
0.3 116 0 512.39 339 685 3.87 0.00
TokenLifecycle
1.0 0 0 0.00 0 0 0.00 0.00
1.1 48 0 1980.50 653 2290 1.60 0.00
ValidateToken
2.0 0 0 0.00 0 0 0.00 0.00
2.1 99 0 616.49 419 820 3.30 0.00
UserCRUD
3.0 0 0 0.00 0 0 0.00 0.00
3.1 1 0 1752.00 1752 1752 0.03 0.00
3.2 112 0 542.37 360 718 3.73 0.00
3.3 2 0 224.50 150 299 0.07 0.00
ProjectCRUD
4.0 0 0 0.00 0 0 0.00 0.00
4.1 0 0 0.00 0 0 0.00 0.00
4.2 59 0 519.63 373 669 1.97 0.00
4.3 1 0 168.00 168 168 0.03 0.00
RoleCRUD
5.0 0 0 0.00 0 0 0.00 0.00
5.1 0 0 0.00 0 0 0.00 0.00
5.2 59 0 513.03 312 695 1.97 0.00
5.3 1 0 238.00 238 238 0.03 0.00
RoleList
6.0 0 0 0.00 0 0 0.00 0.00
6.1 119 0 513.96 341 685 3.97 0.00
RoleAssignmentList
7.0 0 0 0.00 0 0 0.00 0.00
7.1 45 0 520.22 358 641 1.50 0.00
7.2 46 0 484.20 365 615 1.53 0.00
7.3 45 0 489.56 325 679 1.50 0.00
7.4 46 0 515.07 315 657 1.53 0.00
UserRead
8.0 0 0 0.00 0 0 0.00 0.00
8.1 110 0 564.73 390 751 3.67 0.00
8.2 112 0 535.09 370 706 3.73 0.00
ProjectRead
9.0 0 0 0.00 0 0 0.00 0.00
9.1 89 0 517.17 364 661 2.97 0.00
9.2 88 0 523.11 356 691 2.93 0.00
PasswordAuth
10.0 53 0 1103.25 688 1784 1.77 0.00
10.1 52 0 1300.92 788 2009 1.73 0.00
PasswordAuthNegative
11.0 30 0 1048.07 595 1610 1.00 0.00
Rescope
12.0 0 0 0.00 0 0 0.00 0.00
12.1 106 0 577.97 389 732 3.53 0.00
RescopeNegative
13.0 0 0 0.00 0 0 0.00 0.00
13.1 63 0 478.67 343 672 2.10 0.00
SystemScopeAuth
14.0 49 0 1282.45 755 1763 1.63 0.00
ApiKeyCRUD
15.0 0 0 0.00 0 0 0.00 0.00
15.1 0 0 0.00 0 0 0.00 0.00
15.2 29 0 545.83 384 677 0.97 0.00
15.3 29 0 518.10 360 670 0.97 0.00
15.4 1 0 188.00 188 188 0.03 0.00
MappingCRUD
16.0 0 0 0.00 0 0 0.00 0.00
16.1 0 0 0.00 0 0 0.00 0.00
16.2 30 0 497.07 346 668 1.00 0.00
16.3 30 0 528.80 370 737 1.00 0.00
16.4 1 0 143.00 143 143 0.03 0.00
OAuth2ClientCRUD
17.0 0 0 0.00 0 0 0.00 0.00
17.1 0 0 0.00 0 0 0.00 0.00
17.2 30 0 510.97 330 675 1.00 0.00
17.3 30 0 511.30 381 663 1.00 0.00
17.4 1 0 112.00 112 112 0.03 0.00
OAuth2Discovery
18.0 921 0 48.45 9 173 30.70 0.00
18.1 922 0 48.92 7 200 30.73 0.00
ScimRealmRead
19.0 0 0 0.00 0 0 0.00 0.00
19.1 19 0 533.53 351 674 0.63 0.00
19.2 19 0 505.16 378 606 0.63 0.00
19.3 19 0 572.74 460 900 0.63 0.00
ScimSync
20.0 0 0 0.00 0 0 0.00 0.00
20.1 0 0 0.00 0 0 0.00 0.00
20.2 0 0 0.00 0 0 0.00 0.00
20.3 2043 0 14.39 1 786 68.10 0.00
20.4 2042 0 0.00 0 0 68.07 0.00
20.5 2042 0 0.00 0 0 68.07 0.00
20.6 1 0 0.00 0 0 0.03 0.00
Aggregated 9991 0 138.33 1 2290 333.03 0.00

Scenario Metrics

Transaction # Users # Times Run Average (ms) Min (ms) Max (ms) Scenarios/s Iterations
ReadHeavy 6 112 1596.58 1348 1858 3.73 18.67
TokenLifecycle 3 45 2007.56 1667 2290 1.50 15.00
ValidateToken 2 97 619.13 419 820 3.23 48.50
UserCRUD 2 110 543.79 360 718 3.67 55.00
ProjectCRUD 1 58 520.74 373 669 1.93 58.00
RoleCRUD 1 58 514.95 312 695 1.93 58.00
RoleList 2 117 515.14 341 685 3.90 58.50
RoleAssignmentList 3 45 2023.16 1670 2270 1.50 15.00
UserRead 4 109 1103.14 893 1315 3.63 27.25
ProjectRead 3 87 1046.30 804 1260 2.90 29.00
PasswordAuth 4 51 2420.43 1717 3052 1.70 12.75
PasswordAuthNegative 1 29 1037.76 595 1610 0.97 29.00
Rescope 2 104 580.00 389 732 3.47 52.00
RescopeNegative 1 62 480.69 343 672 2.07 62.00
SystemScopeAuth 2 47 1303.62 760 1763 1.57 23.50
ApiKeyCRUD 1 29 1066.31 852 1298 0.97 29.00
MappingCRUD 1 29 1026.76 863 1276 0.97 29.00
OAuth2ClientCRUD 1 29 1030.34 753 1226 0.97 29.00
OAuth2Discovery 3 920 97.84 21 290 30.67 306.67
ScimRealmRead 1 19 1626.26 1367 1782 0.63 19.00
ScimSync 1 2042 14.22 1 786 68.07 2042.00
Aggregated 45 4199 323.21 1 3052 139.97 3016.83

Error Metrics

Method Name # Error
GET GET /SCIM/v2/:domain_id/Users (sync reconcile list) 49 401 Unauthorized: GET /SCIM/v2/:domain_id/Users (sync reconcile list)
POST POST /SCIM/v2/:domain_id/Users (sync provision) 1 401 Unauthorized: POST /SCIM/v2/:domain_id/Users (sync provision)
POST POST /v3/auth/tokens (password, invalid) 68 401 Unauthorized: POST /v3/auth/tokens (password, invalid)
POST POST /v3/auth/tokens (rescope, invalid project) 164 401 Unauthorized: POST /v3/auth/tokens (rescope, invalid project)
GET GET /v3/auth/tokens (validate revoked) 166 404 Not Found: GET /v3/auth/tokens (validate revoked)
GET GET /SCIM/v2/:domain_id/Users (sync reconcile list) 2135 429 Too Many Requests: GET /SCIM/v2/:domain_id/Users (sync reconcile list)

View full report

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown

🧪 Tempest Identity Compatibility Results (advisory, non-blocking)

rust

Totals
======
Ran: 133 tests in 32.4008 sec.
 - Passed: 66
 - Skipped: 4
 - Expected Fail: 0
 - Unexpected Success: 0
 - Failed: 63
Sum of execute time for each test: 23.5654 sec.
Failed test IDs
===== FAILED TESTS (target=rust) =====
tempest.api.identity.admin.v3.test_application_credentials.ApplicationCredentialsV3AdminTest.test_create_application_credential_with_roles[id-3b3dd48f-3388-406a-a9e6-4d078a552d0e]
tempest.api.identity.admin.v3.test_credentials.CredentialsTestJSON.test_credentials_create_get_update_delete[id-7cd59bf9-bda4-4c72-9467-d21cab278355,smoke]
tempest.api.identity.admin.v3.test_default_project_id.TestDefaultProjectId.test_default_project_id[id-d6110661-6a71-49a7-a453-b5e26640ff6d]
tempest.api.identity.admin.v3.test_domains_negative.DomainsNegativeTestJSON.test_create_domain_with_name_length_over_64[id-37b1bbf2-d664-4785-9a11-333438586eae,negative]
tempest.api.identity.admin.v3.test_domains_negative.DomainsNegativeTestJSON.test_delete_active_domain[gate,id-1f3fbff5-4e44-400d-9ca1-d953f05f609b,negative]
tempest.api.identity.admin.v3.test_domains.DomainsTestJSON.test_create_domain_without_description[id-2abf8764-309a-4fa9-bc58-201b799817ad]
tempest.api.identity.admin.v3.test_domains.DomainsTestJSON.test_create_update_delete_domain[id-f2f5b44a-82e8-4dad-8084-0661ea3b18cf,smoke]
tempest.api.identity.admin.v3.test_domain_configuration.DomainConfigurationTestJSON.test_create_domain_config_and_show_config_groups_and_options[id-9e3ff13c-f597-4f01-9377-d6c06c2a1477]
tempest.api.identity.admin.v3.test_domain_configuration.DomainConfigurationTestJSON.test_create_update_and_delete_domain_config_groups_and_opts[id-c7510fa2-6661-4170-9c6b-4783a80651e9]
tempest.api.identity.admin.v3.test_domain_configuration.DomainConfigurationTestJSON.test_show_default_group_config_and_options[id-11a02bf0-6f94-4380-b3b0-c8dc18fc0d22]
tempest.api.identity.admin.v3.test_domains.DomainsTestJSON.test_domain_delete_cascades_content[id-d8d318b7-d1b3-4c37-94c5-3c5ba0b121ea]
tempest.api.identity.admin.v3.test_domains.DomainsTestJSON.test_list_domains_filter_by_enabled[id-3fd19840-65c1-43f8-b48c-51bdd066dff9]
tempest.api.identity.admin.v3.test_groups.GroupsV3TestJSON.test_group_users_add_list_delete[id-1598521a-2f36-4606-8df9-30772bd51339,smoke]
tempest.api.identity.admin.v3.test_groups.GroupsV3TestJSON.test_list_user_groups[id-64573281-d26a-4a52-b899-503cb0f4e4ec]
setUpClass (tempest.api.identity.admin.v3.test_endpoint_groups.EndPointGroupsTest)
tempest.api.identity.admin.v3.test_list_projects.ListProjectsTestJSON.test_list_projects_with_enabled[id-0fe7a334-675a-4509-b00e-1c4b95d5dae8]
tempest.api.identity.admin.v3.test_list_projects.ListProjectsTestJSON.test_list_projects_with_parent[id-6edc66f5-2941-4a17-9526-4073311c1fac]
tempest.api.identity.admin.v3.test_oauth_consumers.OAUTHConsumersV3Test.test_create_and_show_consumer[id-c8307ea6-a86c-47fd-ae7b-5b3b2caca76d]
tempest.api.identity.admin.v3.test_oauth_consumers.OAUTHConsumersV3Test.test_delete_consumer[id-fdfa1b7f-2a31-4354-b2c7-f6ae20554f93]
tempest.api.identity.admin.v3.test_oauth_consumers.OAUTHConsumersV3Test.test_list_consumers[id-09ca50de-78f2-4ffb-ac71-f2254036b2b8]
tempest.api.identity.admin.v3.test_oauth_consumers.OAUTHConsumersV3Test.test_update_consumer[id-080a9b1a-c009-47c0-9979-5305bf72e3dc]
tempest.api.identity.admin.v3.test_inherits.InheritsV3TestJSON.test_inherit_assign_check_revoke_roles_on_projects_group[id-26021436-d5a4-4256-943c-ded01e0d4b45]
tempest.api.identity.admin.v3.test_inherits.InheritsV3TestJSON.test_inherit_assign_check_revoke_roles_on_projects_user[id-18b70e45-7687-4b72-8277-b8f1a47d7591]
tempest.api.identity.admin.v3.test_inherits.InheritsV3TestJSON.test_inherit_assign_list_check_revoke_roles_on_domains_group[id-c7a8dda2-be50-4fb4-9a9c-e830771078b1]
tempest.api.identity.admin.v3.test_inherits.InheritsV3TestJSON.test_inherit_assign_list_check_revoke_roles_on_domains_user[id-4e6f0366-97c8-423c-b2be-41eae6ac91c8]
tempest.api.identity.admin.v3.test_inherits.InheritsV3TestJSON.test_inherit_assign_list_revoke_user_roles_on_domain[id-3acf666e-5354-42ac-8e17-8b68893bcd36]
tempest.api.identity.admin.v3.test_inherits.InheritsV3TestJSON.test_inherit_assign_list_revoke_user_roles_on_project_tree[id-9f02ccd9-9b57-46b4-8f77-dd5a736f3a06]
tempest.api.identity.admin.v3.test_list_projects.ListProjectsStaticTestJSON.test_list_projects[id-1d830662-22ad-427c-8c3e-4ec854b0af44]
tempest.api.identity.admin.v3.test_projects_negative.ProjectsNegativeStaticTestJSON.test_create_projects_name_length_over_64[id-502b6ceb-b0c8-4422-bf53-f08fdb21e2f0,negative]
tempest.api.identity.admin.v3.test_list_users.UsersV3TestJSON.test_list_users_with_not_enabled[id-bff8bf2f-9408-4ef5-b63a-753c8c2124eb]
tempest.api.identity.admin.v3.test_project_tags.IdentityV3ProjectTagsTest.test_list_update_delete_project_tags[id-7c123aac-999d-416a-a0fb-84b915ab10de]
tempest.api.identity.admin.v3.test_tokens.TokensV3TestJSON.test_get_available_domain_scopes[id-ec5ecb05-af64-4c04-ac86-4d9f6f12f185]
tempest.api.identity.admin.v3.test_tokens.TokensV3TestJSON.test_rescope_token[id-565fa210-1da1-4563-999b-f7b5b67cf112]
tempest.api.identity.admin.v3.test_roles.RolesV3TestJSON.test_assignments_for_domain_roles[id-3859df7e-5b78-4e4d-b10e-214c8953842a]
tempest.api.identity.admin.v3.test_roles.RolesV3TestJSON.test_assignments_for_implied_roles_create_delete[id-c8828027-df48-4021-95df-b65b92c7429e]
tempest.api.identity.admin.v3.test_roles.RolesV3TestJSON.test_grant_list_revoke_role_to_group_on_domain[id-4bf8a70b-e785-413a-ad53-9f91ce02faa7]
tempest.api.identity.admin.v3.test_roles.RolesV3TestJSON.test_grant_list_revoke_role_to_group_on_project[id-cbf11737-1904-4690-9613-97bcbb3df1c4]
tempest.api.identity.admin.v3.test_roles.RolesV3TestJSON.test_grant_list_revoke_role_to_group_on_system[id-c888fe4f-8018-48db-b959-542225c1b4b6]
tempest.api.identity.admin.v3.test_roles.RolesV3TestJSON.test_grant_list_revoke_role_to_user_on_domain[id-6c9a2940-3625-43a3-ac02-5dcec62ef3bd]
tempest.api.identity.admin.v3.test_projects.ProjectsTestJSON.test_create_is_domain_project[id-a7eb9416-6f9b-4dbb-b71b-7f73aaef59d5]
tempest.api.identity.admin.v3.test_roles.RolesV3TestJSON.test_implied_domain_roles[id-eb1e1c24-1bc4-4d47-9748-e127a1852c82]
tempest.api.identity.admin.v3.test_roles.RolesV3TestJSON.test_implied_roles_create_check_show_delete[id-c90c316c-d706-4728-bcba-eb1912081b69]
tempest.api.identity.admin.v3.test_roles.RolesV3TestJSON.test_role_create_update_show_list[id-18afc6c0-46cf-4911-824e-9989cc056c3a,smoke]
tempest.api.identity.admin.v3.test_projects.ProjectsTestJSON.test_project_create_with_parent[id-1854f9c0-70bc-4d11-a08a-1c789d339e3d]
tempest.api.identity.admin.v3.test_projects.ProjectsTestJSON.test_project_get_equals_list[id-d1db68b6-aebe-4fa0-b79d-d724d2e21162]
tempest.api.identity.v3.test_api_discovery.TestApiDiscovery.test_api_media_types[id-657c1970-4722-4189-8831-7325f3bc4265,smoke]
tempest.api.identity.v3.test_api_discovery.TestApiDiscovery.test_api_version_resources[id-b9232f5e-d9e5-4d97-b96c-28d3db4de1bd,smoke]
tempest.api.identity.v3.test_api_discovery.TestApiDiscovery.test_identity_v3_existence[id-79aec9ae-710f-4c54-a4fc-3aa25b4feac3]
tempest.api.identity.v3.test_api_discovery.TestApiDiscovery.test_list_api_versions[id-721f480f-35b6-46c7-846e-047e6acea0dc,smoke]
tempest.api.identity.v3.test_projects.IdentityV3ProjectsTest.test_list_projects_returns_only_authorized_projects[id-86128d46-e170-4644-866a-cc487f699e1d]
tempest.api.identity.admin.v3.test_trusts.TrustsV3TestJSON.test_get_trusts_all[id-4773ebd5-ecbf-4255-b8d8-b63e6f72b65d,smoke]
tempest.api.identity.v3.test_tokens.TokensV3Test.test_validate_token[id-a9512ac3-3909-48a4-b395-11f438e16260]
tempest.api.identity.admin.v3.test_users.UsersV3TestJSON.test_list_user_projects[id-a831e70c-e35b-430b-92ed-81ebbc5437b8]
tempest.api.identity.admin.v3.test_trusts.TrustsV3TestJSON.test_get_trusts_query[id-6268b345-87ca-47c0-9ce3-37792b43403a]
tempest.api.identity.admin.v3.test_trusts.TrustsV3TestJSON.test_trust_expire[id-0ed14b66-cefd-4b5c-a964-65759453e292]
tempest.api.identity.admin.v3.test_trusts.TrustsV3TestJSON.test_trust_impersonate[id-5a0a91a4-baef-4a14-baba-59bf4d7fcace]
tempest.api.identity.admin.v3.test_trusts.TrustsV3TestJSON.test_trust_noimpersonate[id-ed2a8779-a7ac-49dc-afd7-30f32f936ed2]
tempest.api.identity.admin.v3.test_users_negative.UsersNegativeTest.test_create_user_for_non_existent_domain[id-e75f006c-89cc-477b-874d-588e4eab4b17,negative]
tempest.api.identity.v3.test_application_credentials.ApplicationCredentialsV3Test.test_create_application_credential[id-8080c75c-eddc-4786-941a-c2da7039ae61]
tempest.api.identity.v3.test_application_credentials.ApplicationCredentialsV3Test.test_create_application_credential_expires[id-852daf0c-42b5-4239-8466-d193d0543ed3]
tempest.api.identity.v3.test_application_credentials.ApplicationCredentialsV3Test.test_list_application_credentials[id-ff0cd457-6224-46e7-b79e-0ada4964a8a6]
tempest.api.identity.v3.test_application_credentials.ApplicationCredentialsV3Test.test_query_application_credentials[id-9bb5e5cc-5250-493a-8869-8b665f6aa5f6]
tempest.api.identity.v3.test_catalog.IdentityCatalogTest.test_catalog_standardization[id-56b57ced-22b8-4127-9b8a-565dfb0207e2]
===== END FAILED TESTS (target=rust) =====

View full run

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown

🐰 Bencher Report

Projectkeystone
Branchopenfga
Testbedubuntu-latest
Click to view all benchmark results
BenchmarkLatencyBenchmark Result
nanoseconds (ns)
(Result Δ%)
Upper Boundary
nanoseconds (ns)
(Limit %)
Command_Serde/apply/remove📈 view plot
🚷 view threshold
134,830.00 ns
(-50.63%)Baseline: 273,076.45 ns
1,352,565.88 ns
(9.97%)
Command_Serde/apply/set📈 view plot
🚷 view threshold
142,720.00 ns
(-67.73%)Baseline: 442,332.34 ns
3,265,766.51 ns
(4.37%)
Command_Serde/pack/delete📈 view plot
🚷 view threshold
122.67 ns
(+4.11%)Baseline: 117.82 ns
155.36 ns
(78.96%)
Command_Serde/pack/delete_index📈 view plot
🚷 view threshold
109.29 ns
(+3.99%)Baseline: 105.10 ns
138.45 ns
(78.94%)
Command_Serde/pack/set📈 view plot
🚷 view threshold
215.83 ns
(+13.76%)Baseline: 189.72 ns
245.14 ns
(88.04%)
Command_Serde/pack/set_index📈 view plot
🚷 view threshold
109.13 ns
(+3.89%)Baseline: 105.04 ns
139.00 ns
(78.51%)
Command_Serde/unpack/delete📈 view plot
🚷 view threshold
192.83 ns
(+3.62%)Baseline: 186.09 ns
267.37 ns
(72.12%)
Command_Serde/unpack/delete_index📈 view plot
🚷 view threshold
159.75 ns
(+3.07%)Baseline: 154.99 ns
216.25 ns
(73.87%)
Command_Serde/unpack/set📈 view plot
🚷 view threshold
291.62 ns
(+11.92%)Baseline: 260.55 ns
355.47 ns
(82.04%)
Command_Serde/unpack/set_index📈 view plot
🚷 view threshold
156.79 ns
(+2.84%)Baseline: 152.46 ns
210.54 ns
(74.47%)
Payload_encryption/pack/remove_cmd📈 view plot
🚷 view threshold
115.15 ns
(+2.29%)Baseline: 112.57 ns
149.98 ns
(76.78%)
Payload_encryption/pack/set_cmd📈 view plot
🚷 view threshold
205.57 ns
(+4.25%)Baseline: 197.18 ns
263.18 ns
(78.11%)
Payload_encryption/unpack/remove_cmd📈 view plot
🚷 view threshold
209.89 ns
(+7.45%)Baseline: 195.33 ns
283.21 ns
(74.11%)
Payload_encryption/unpack/set_cmd📈 view plot
🚷 view threshold
304.91 ns
(+12.66%)Baseline: 270.65 ns
375.05 ns
(81.30%)
Raft_1Node_Latency/prefix/1node📈 view plot
🚷 view threshold
2,760,500.00 ns
(-7.02%)Baseline: 2,968,944.67 ns
7,777,574.56 ns
(35.49%)
Raft_1Node_Latency/read/1node📈 view plot
🚷 view threshold
42,509.00 ns
(+13.91%)Baseline: 37,318.91 ns
51,652.80 ns
(82.30%)
Raft_1Node_Latency/remove/1node📈 view plot
🚷 view threshold
380,820.00 ns
(-68.92%)Baseline: 1,225,240.47 ns
11,602,622.84 ns
(3.28%)
Raft_1Node_Latency/write/1node📈 view plot
🚷 view threshold
384,290.00 ns
(-61.59%)Baseline: 1,000,391.25 ns
7,589,559.30 ns
(5.06%)
build_snapshot/default📈 view plot
🚷 view threshold
113,770.00 ns
(-9.11%)Baseline: 125,177.23 ns
277,033.80 ns
(41.07%)
fernet token/project📈 view plot
🚷 view threshold
1,450.70 ns
(+2.04%)Baseline: 1,421.63 ns
1,791.61 ns
(80.97%)
get_data_keyspace📈 view plot
🚷 view threshold
0.31 ns
(-0.39%)Baseline: 0.32 ns
0.39 ns
(81.20%)
get_db📈 view plot
🚷 view threshold
0.31 ns
(-0.84%)Baseline: 0.32 ns
0.39 ns
(80.96%)
get_fernet_token_timestamp/project📈 view plot
🚷 view threshold
138.02 ns
(-1.15%)Baseline: 139.63 ns
179.37 ns
(76.95%)
get_keyspace📈 view plot
🚷 view threshold
4.43 ns
(-24.91%)Baseline: 5.89 ns
13.79 ns
(32.09%)
🐰 View full continuous benchmarking report in Bencher

Keystone role assignments are a relationship graph; OpenFGA models that
natively, letting deployments that already run it as their central authz
store put OpenStack and non-OpenStack resources under one model with
group/implication resolution done once, not per-consumer.

- Config-only entity<->object mapping (crates/config), no new
  Keystone-side mapping table
- listing shapes this driver structurally cannot answer (no actor and no
  target, or role-only) return 501 via a new
AssignmentProviderError::NotImplement, not backend faults
- object enumeration uses streamed-list-objects instead of list-objects
  to avoid its silent 1000-result truncation
- bounded concurrency (max_concurrency, default 10) on every fan-out
  over actor/target representations and role relations
- retry with exponential backoff on 429/5xx/transient transport errors

See doc/src/adr/0033-openfga-assignment-driver.md, including the
Negative consequences: this driver does not sync Keystone group
membership into OpenFGA, so effective-mode token issuance needs that
pipeline built externally before switching drivers.

Signed-off-by: Artem Goncharov <artem.goncharov@gmail.com>
@gtema
gtema added this pull request to the merge queue Sep 4, 2026
Merged via the queue into main with commit 5fa1e2a Sep 4, 2026
36 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant