3.12. Authorization security
Up: 3. Developer guide
Prev: 3.11. Authentication security
Next: 3.13. Input validation
Sections:
- Overview
- Roles and principals
- LDAP integration
- Access control for releases
- Access control for tokens
- Implementation patterns
- Caching behavior
- Implementation references
Overview
ATR uses role-based access control (RBAC) where roles are derived from ASF LDAP group memberships. Authentication (covered in Authentication security) establishes who a user is; authorization determines what they can do.
The authorization model is committee-centric: most permissions are granted based on a user's relationship to a committee (PMC membership) or project (committer status).
Roles and principals
Note
This documents the current status of roles in the application, which will be reorganized, per these Issues:
- Review permissions for all actions in ATR
- Allow release managers to be designated
- Promotion permissions for phase transitions and distributions
ATR recognizes the following roles, derived from ASF LDAP:
-
Public: Unauthenticated users. Can view public information about releases and projects.
-
Committer: Any authenticated ASF committer. Can create Personal Access Tokens and view their own committees and projects. Determined by existence in LDAP
ou=people,dc=apache,dc=org. -
Project Participant: A committer who is a member of a specific project. Can start releases, upload artifacts, and cast votes for that project. Determined by the
memberattribute in the project's LDAP group. -
PMC Member: A committer who is on the PMC (Project Management Committee) for a specific committee. Has all participant permissions plus can resolve votes, finish releases, configure project settings, and manage signing keys. Determined by the
ownerattribute in the committee's LDAP group. -
Chair: A PMC chair. Currently has the same permissions as PMC Member in ATR. Determined by membership in
cn=pmc-chairs,ou=groups,ou=services,dc=apache,dc=org. -
ASF Member: An ASF Member. Currently has the same permissions as a regular committer in ATR, though this may change. Determined by membership in
cn=member,ou=groups,dc=apache,dc=org. -
Infrastructure Root: ASF Infrastructure team with root access. Has administrative capabilities. Determined by membership in
cn=infrastructure-root,ou=groups,ou=services,dc=apache,dc=org. -
Tooling Team: Members of the ASF Tooling team. Treated as PMC members of the "tooling" committee. Determined by membership in
cn=tooling,ou=groups,ou=services,dc=apache,dc=org.
LDAP integration
Authorization data is fetched from ASF LDAP using the principal module. The key LDAP bases are:
ou=people,dc=apache,dc=org- All committersou=project,ou=groups,dc=apache,dc=org- Project and committee groupscn=member,ou=groups,dc=apache,dc=org- ASF Memberscn=pmc-chairs,ou=groups,ou=services,dc=apache,dc=org- PMC Chairscn=infrastructure-root,ou=groups,ou=services,dc=apache,dc=org- Infrastructure rootcn=tooling,ou=groups,ou=services,dc=apache,dc=org- Tooling team
The Committer class fetches a user's full authorization profile from LDAP, including their committee memberships (PMC membership) and project participations (committer access).
Access control for releases
Release operations have the following access requirements:
View release information (public pages, download links):
- Allowed for: Everyone, including unauthenticated users
Start a new release:
- Allowed for: Project participants (committers on the project)
- Checked via:
is_participant_of(project.committee_name)
Upload release artifacts:
- Allowed for: Project participants
- Additional constraint: Must be the user who started the release, or a PMC member
Cast a vote on a release:
- Allowed for: Project participants
- Constraint: Cannot vote multiple times; can change existing vote
Resolve a vote (tally votes and determine outcome):
- Allowed for: PMC members only
- Checked via:
is_member_of(project.committee_name)
Finish a release (publish to distribution):
- Allowed for: PMC members only
- Constraint: Vote must be resolved with a passing result
Cancel or delete a release:
- Draft releases: Project participants
- Finished releases: ATR administrators only
Access control for tokens
Token operations apply to the authenticated user:
Create a Personal Access Token:
- Allowed for: Any authenticated committer
- Constraint: Can only create tokens for themselves
List own Personal Access Tokens:
- Allowed for: Any authenticated committer
- Constraint: Can only see their own tokens
Revoke a Personal Access Token:
- Allowed for: The token owner, or administrators
- Constraint: Users can only revoke their own tokens (unless admin)
Exchange PAT for JWT:
- Allowed for: Anyone with a valid PAT
- Note: This is an unauthenticated endpoint; the PAT serves as the credential
Implementation patterns
Authorization checks in ATR follow consistent patterns.
Checking PMC membership
To verify a user is a PMC member for a committee:
from atr.principal import Authorisation
auth = await Authorisation()
if not auth.is_member_of(committee_name):
raise Forbidden("PMC membership required")
Checking project participation
To verify a user is a committer on a project:
auth = await Authorisation()
if not auth.is_participant_of(project.committee_name):
raise Forbidden("Project participation required")
Getting all memberships
To get the set of committees or projects a user belongs to:
auth = await Authorisation()
committees = auth.member_of() # Returns frozenset of committee names
projects = auth.participant_of() # Returns frozenset of project names
Web vs API authorization
For web requests, the Authorisation class reads the session automatically:
auth = await Authorisation() # Uses ASFQuart session
For API requests, the ASF UID is extracted from the JWT and passed explicitly:
auth = await Authorisation(asf_uid) # Uses LDAP lookup
Both paths use the same authorization logic and caching.
Caching behavior
LDAP queries are expensive, so authorization data is cached in principal.Cache. The cache stores:
member_of- Set of committees where the user is a PMC memberparticipant_of- Set of projects where the user is a committerlast_refreshed- Timestamp of last LDAP query
The cache TTL is 300 seconds (cache_for_at_most_seconds). When the cache is stale, the next authorization check triggers an LDAP refresh.
The cache is per-user and in-memory. It does not persist across server restarts. If LDAP group memberships change, users may need to wait up to 5 minutes for ATR to reflect the change, or log out and back in.
Test mode
When ALLOW_TESTS is enabled in the configuration, a special "test" user and "test" committee are available. All authenticated users are automatically added to the test committee for testing purposes. This should never be enabled in production.
Implementation references
principal.py- Core authorization classes and LDAP integrationweb.py- Request context and committer accessldap.py- Low-level LDAP search functionality