The solution requires addressing multiple layers of the permission stack:
1. LDAP Group Synchronization Configuration
Verify your LDAP sync is configured to propagate not just role membership but also granular permissions. In Site Administration → Authentication → LDAP Settings, ensure “Sync Granular Permissions” is enabled. Service accounts often need manual permission refresh after group changes.
2. Granular RBAC Configuration
Navigate to Site Administration → Security → Role Permissions. For your QA_Admin role, explicitly enable:
- TEST_CASE_READ
- TEST_CASE_EXPORT
- API_ACCESS
Then go to Project Administration → Project Users and verify the service account shows these permissions at the project level, not just inherited from global roles.
3. Test Case Export Permission Scoping
The export operation requires specific entity-level permissions. Run this query in the database to verify:
SELECT user_name, permission_name, project_id
FROM auth_permissions
WHERE user_name='svc_qa_export'
If EXPORT_TEST_CASES isn’t listed for your target projects, manually add it through the security matrix.
4. SSO Token Validation for Export Operations
For REST API calls, your OAuth client configuration in Okta must include:
- Custom scope: “alm.test.export”
- Token claim: “export_permissions” with value “test_cases”
In ALM, update the SSO configuration (Site Administration → Authentication → SSO Settings) to map this claim to the internal EXPORT_TEST_CASES privilege.
5. Force Permission Cache Refresh
After making changes, clear the permission cache:
alm-admin refresh-permissions --user svc_qa_export
alm-admin validate-sso-claims --user svc_qa_export
The key issue is that service accounts with SSO authentication need both LDAP-derived roles AND explicit API permission grants. The permission denied error occurs because the REST API validator checks direct permissions first, before falling back to role-based permissions. This is a security design to prevent privilege escalation through group membership alone.
After implementing these changes, test with a simple export API call and verify the token includes the required claims in the authorization header.