Skip to content

Effective project handling - #18460

Draft
markylaing wants to merge 39 commits into
canonical:mainfrom
markylaing:effective-project-handling
Draft

Effective project handling#18460
markylaing wants to merge 39 commits into
canonical:mainfrom
markylaing:effective-project-handling

Conversation

@markylaing

@markylaing markylaing commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Rewires effective project handling so that calls to the authorizer use the effective project rather than the requested project.

This is achieved by moving effective project handling to the TLS authorizer.

The motivation for this change is a) confusion around creating resources and then not being able to view them (see linked issue), b) we'll be always using the effective project any way once we've moved to using entity IDs instead of URLs, and c) the custom handling in the TLS authorizer will disappear once we've removed restricted TLS clients.

Closes #17257
Depends on #18440

Checklist

Signed-off-by: Mark Laing <mark.laing@canonical.com>
Signed-off-by: Mark Laing <mark.laing@canonical.com>
Signed-off-by: Mark Laing <mark.laing@canonical.com>
Signed-off-by: Mark Laing <mark.laing@canonical.com>
Previously these were "allowProjectResourceList", but these
handlers list backups or snapshots for a single instance/volume
and not in the whole project.

Signed-off-by: Mark Laing <mark.laing@canonical.com>
Signed-off-by: Mark Laing <mark.laing@canonical.com>
This functionality is now covered by marking an endpoint as project
specific and setting the all-projects mode.

The only remaining callsite is for GET /1.0/images, which cannot
apply the global project permission check because it allows
untrusted requests. Necessary logic is moved to the imagesGet
AccessHandler.

Signed-off-by: Mark Laing <mark.laing@canonical.com>
@markylaing markylaing added this to the lxd-6.9 milestone Jun 16, 2026
@markylaing
markylaing force-pushed the effective-project-handling branch 3 times, most recently from d5f1b91 to fe40822 Compare June 16, 2026 15:04
@markylaing
markylaing requested a review from Copilot June 16, 2026 15:33

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR rewires project-aware authorization so that permission checks are performed against the effective project (e.g., falling back to default when a feature is disabled in the requested project), centralizing the behavior in the TLS authorizer and adding global project checks for project-specific endpoints.

Changes:

  • Introduces ProjectSpecific endpoints plus global handling of project/all-projects authorization checks in the API router.
  • Updates many project-scoped endpoints to build entity URLs using the effective project and to use new AllProjectsMode behavior.
  • Enhances restricted TLS identity handling by carrying per-project feature flags and updating TLS authorization logic; adjusts tests accordingly.

Reviewed changes

Copilot reviewed 33 out of 33 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
test/suites/auth.sh Updates auth integration tests to validate effective-project behavior for restricted callers and creation entitlements.
lxd/storage_volumes.go Marks endpoints project-specific, shifts listing access handling, and enforces effective-project checks for volume operations and creation.
lxd/storage_volumes_state.go Marks volume state endpoint as project-specific for global project authorization.
lxd/storage_volumes_snapshot.go Marks snapshot endpoints project-specific and uses effective-project access checks.
lxd/storage_volumes_backup.go Marks backup endpoints project-specific and uses effective-project access checks.
lxd/storage_buckets.go Marks bucket endpoints project-specific and refactors bucket access handler to account for effective project.
lxd/request/requestor.go Changes restricted TLS allowed-projects representation to include feature flags; adds helpers.
lxd/project/permissions.go Switches used-by filtering to use standard authorizer checks (no “ignore effective project” variants).
lxd/project/limits/permissions_test.go Updates test setup to match new Projects map shape.
lxd/profiles.go Marks endpoints project-specific; refactors access handling to use effective-project URLs and adjusts listing behavior.
lxd/placement_groups.go Marks endpoints project-specific and updates list access handling.
lxd/operations.go Marks operations endpoint project-specific and allows all-projects mode for authenticated callers.
lxd/networks.go Marks endpoints project-specific; refactors network access handler and listing to use effective-project authorization.
lxd/network_zones.go Marks endpoints project-specific; refactors access handler and listing to use effective-project authorization.
lxd/network_zones_records.go Marks zone record endpoints project-specific.
lxd/network_peer.go Marks peer endpoints project-specific.
lxd/network_load_balancers.go Marks load balancer endpoints project-specific.
lxd/network_forwards.go Marks forward endpoints project-specific.
lxd/network_allocations.go Marks allocations endpoint project-specific and updates permission checks to align with new effective-project handling.
lxd/network_acls.go Marks ACL endpoints project-specific; refactors ACL access handling and listing to use effective-project authorization.
lxd/instances.go Marks endpoints project-specific and switches list/bulk handlers to new global access approach.
lxd/instance_logs.go Marks log endpoints project-specific.
lxd/images.go Marks image endpoints project-specific; reworks image list/get/export access logic to align with effective-project model and global project visibility checks.
lxd/events.go Marks events endpoint project-specific and allows all-projects mode for authenticated callers.
lxd/devlxd.go Refactors devlxd project enforcement helper to return project name and reuse it.
lxd/devlxd_storage.go Updates devlxd storage volume creation/access checks to validate effective project/feature enablement.
lxd/db/cluster/certificates_legacy.go Adds DB helper to load legacy restricted TLS allowed projects along with feature flags.
lxd/daemon.go Adds ProjectSpecific + AllProjectsMode plumbing and centralizes project/all-projects global authorization checks.
lxd/auth/types.go Removes “WithoutEffectiveProject” authorizer interface variants.
lxd/auth/drivers/tls.go Moves effective-project logic for restricted TLS clients into the TLS authorizer using feature flags and creation entitlements.
lxd/auth/drivers/tls_test.go Updates TLS authorizer tests for feature-flagged project access.
lxd/auth/drivers/openfga.go Removes context-driven effective-project rewriting and relies on callers providing correct effective-project URLs.
lxd/api_replicators.go Marks endpoints project-specific and sets all-projects behavior for listing.

Comment thread lxd/storage_buckets.go
Comment thread lxd/auth/drivers/tls.go
Comment thread lxd/request/requestor.go Outdated
Comment thread lxd/auth/drivers/tls.go Outdated
Comment thread lxd/db/cluster/certificates_legacy.go
Signed-off-by: Mark Laing <mark.laing@canonical.com>
Signed-off-by: Mark Laing <mark.laing@canonical.com>
Signed-off-by: Mark Laing <mark.laing@canonical.com>
Signed-off-by: Mark Laing <mark.laing@canonical.com>
Signed-off-by: Mark Laing <mark.laing@canonical.com>
Signed-off-by: Mark Laing <mark.laing@canonical.com>
Signed-off-by: Mark Laing <mark.laing@canonical.com>
Signed-off-by: Mark Laing <mark.laing@canonical.com>
Signed-off-by: Mark Laing <mark.laing@canonical.com>
Rather than accessing it from context immediately afterwards.

Signed-off-by: Mark Laing <mark.laing@canonical.com>
This is a change in behaviour but is unlikely to cause breakages
since features.storage.volumes is initially true when creating a
project.

Signed-off-by: Mark Laing <mark.laing@canonical.com>
Enforce the storage volume feature on the instance project and set
it in context as the effective project so that the main API
handler has access to it.

Signed-off-by: Mark Laing <mark.laing@canonical.com>
Use the effective project for the authorization check and set it in
the request context.

Signed-off-by: Mark Laing <mark.laing@canonical.com>
Signed-off-by: Mark Laing <mark.laing@canonical.com>
…ecks.

Signed-off-by: Mark Laing <mark.laing@canonical.com>
Removes `addStorageBucketDetailsToContext` and moves logic directly
into the access handler. If the entitlement is
`can_create_storage_buckets`, the access handler checks against
the effective project URL.

Signed-off-by: Mark Laing <mark.laing@canonical.com>
Removes `addProfileDetailsToContext` and moves logic directly
into the access handler. If the entitlement is
`can_create_profiles`, the access handler checks against
the effective project URL.

Signed-off-by: Mark Laing <mark.laing@canonical.com>
Signed-off-by: Mark Laing <mark.laing@canonical.com>
Removes `addNetworkDetailsToContext` and moves logic directly
into the access handler. If the entitlement is
`can_create_networks`, the access handler checks against
the effective project URL.

Signed-off-by: Mark Laing <mark.laing@canonical.com>
Signed-off-by: Mark Laing <mark.laing@canonical.com>
Removes `addNetworkZoneDetailsToContext` and moves logic directly
into the access handler. If the entitlement is
`can_create_network_zones`, the access handler checks against
the effective project URL.

Signed-off-by: Mark Laing <mark.laing@canonical.com>
Signed-off-by: Mark Laing <mark.laing@canonical.com>
Previously we did not check the effective project access checks
at all, so it would likely have been broken for fine-grained
identities.

Signed-off-by: Mark Laing <mark.laing@canonical.com>
Signed-off-by: Mark Laing <mark.laing@canonical.com>
Signed-off-by: Mark Laing <mark.laing@canonical.com>
If the entitlement is `can_create_image_aliases`, the access
handler checks against the effective project URL.

Signed-off-by: Mark Laing <mark.laing@canonical.com>
Signed-off-by: Mark Laing <mark.laing@canonical.com>
Signed-off-by: Mark Laing <mark.laing@canonical.com>
- Always check the secret first. When getting an image secret, the
  token operation contains the full image fingerprint, so expect
  the caller to have sent it.
- Set `publicOnly` to true if the caller cannot view the requested
  project. In practice this means that e.g. a restricted TLS client
  without access to the default project will only query for public
  images without them being filtered out later.
- If the caller cannot view the requested project, and the
  requested project is not "default", return 404.
- Check permission on the image using the effective project.

Signed-off-by: Mark Laing <mark.laing@canonical.com>
- Move more access logic into the access handler, including
  whether to only query for public images (boolean now set in
  request context).
- Use effective project for access checks.

Signed-off-by: Mark Laing <mark.laing@canonical.com>
Signed-off-by: Mark Laing <mark.laing@canonical.com>
Signed-off-by: Mark Laing <mark.laing@canonical.com>
@markylaing
markylaing force-pushed the effective-project-handling branch from fe40822 to 68404b3 Compare June 16, 2026 16:51
@markylaing

Copy link
Copy Markdown
Contributor Author

Addressed copilot comments

@markylaing markylaing self-assigned this Jun 16, 2026
@tomponline tomponline modified the milestones: lxd-6.9, lxd-6.10, 26.04 Jun 17, 2026
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.

Fine-grained authorizer does not account for feature flags on entity creation

3 participants