Alpha 2 Software: ATR is available as Alpha software. You can test the release process. Actual releases can be downloaded and committed to svn.

3.12. Authorization security

Up: 3. Developer guide

Prev: 3.11. Authentication security

Next: 3.13. Input validation

Sections:

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:

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 member attribute 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 owner attribute 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 committers
  • ou=project,ou=groups,dc=apache,dc=org - Project and committee groups
  • cn=member,ou=groups,dc=apache,dc=org - ASF Members
  • cn=pmc-chairs,ou=groups,ou=services,dc=apache,dc=org - PMC Chairs
  • cn=infrastructure-root,ou=groups,ou=services,dc=apache,dc=org - Infrastructure root
  • cn=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

Access control for check ignores

Check ignores allow committee members to suppress specific check results from the warning and error counts. The ignores page is accessible to any authenticated committer, but only PMC members of the project's committee can add, update, or delete ignore rules. The storage writer validates that the user is a member of the committee that owns the target project by calling is_member_of(project.committee_name). As additional protection, the writer also validates that the project belongs to the authorized committee before performing any operation. This ensures that even if the calling code passes an incorrect project name, the operation will be rejected.

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 member
  • participant_of - Set of projects where the user is a committer
  • last_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 integration
  • web.py - Request context and committer access
  • ldap.py - Low-level LDAP search functionality