Skip to content

Coordinator Capability implementation - #1955

Draft
Emantor wants to merge 9 commits into
labgrid-project:masterfrom
Emantor:topic/capabilities
Draft

Coordinator Capability implementation#1955
Emantor wants to merge 9 commits into
labgrid-project:masterfrom
Emantor:topic/capabilities

Conversation

@Emantor

@Emantor Emantor commented Aug 12, 2026

Copy link
Copy Markdown
Member

Description
Implement capabilities and checks on the coordinator side.
This relies on the existing identity pull request and will require changes.

Happy for any feedback on the implementation, I know that documentation is still missing, but at this point we should start discussing the implementation.

The Tests currently only really test the happy path, testing the denied path will become easier once we have policies, but I can try to figure this out for this PR if desired.

Checklist

  • Documentation for the feature
  • Tests for the feature
  • Add a section on how to use the feature to doc/usage.rst
  • Add a section on how to use the feature to doc/development.rst
  • PR has been tested
  • Man pages have been regenerated

asher-pem-arm and others added 8 commits July 14, 2026 13:50
Add client and server interceptors which attach labgrid identity metadata
to gRPC calls and expose it to coordinator RPC handlers.

Use the metadata identity to register client and exporter stream sessions
while keeping startup-message handling as a deprecated fallback for older
clients and exporters.

Signed-off-by: Asher Pemberton <asher.pemberton@arm.com>
Reviewed-by: Asher Pemberton <asher.pemberton@arm.com> # gatekeeper
Co-authored-by: Luke Beardsmore <luke.beardsmore2@arm.com>
Allow AcquirePlace, ReleasePlace and CreateReservation to identify the
caller from gRPC metadata instead of requiring identity to come only from
an established ClientStream session.

Keep the existing ClientStream session lookup as a fallback so older
clients which still send startup messages on the stream continue to work.

Signed-off-by: Asher Pemberton <asher.pemberton@arm.com>
Reviewed-by: Asher Pemberton <asher.pemberton@arm.com> # gatekeeper
Co-authored-by: Luke Beardsmore <luke.beardsmore2@arm.com>
Send StartupDone alongside identity metadata so new clients and exporters
remain compatible with older coordinators. Create sessions immediately
from identity metadata when available, while retaining StartupDone as a
deprecated fallback.

Signed-off-by: Asher Pemberton <asher.pemberton@arm.com>
Reviewed-by: Asher Pemberton <asher.pemberton@arm.com> # gatekeeper
Taken verbatim from the authentication github discussion [1].

[1]: labgrid-project#1883

Signed-off-by: Rouven Czerwinski <rouven.czerwinski@linaro.org>
This is a stop-gap until we have policies to assign capabilities.

Signed-off-by: Rouven Czerwinski <rouven.czerwinski@linaro.org>
Implement capabilities by using a decorator for unary calls and checking
permissions manually for stream calls. Capabilities with more
scoping (owned vs any) do not use the decorator and instead check
manually.

With the capabilities checked by the Coordinator, future Labgrid
versions will be able to use policies to assign capabilities to specific
identities and thus restrict which gRPC calls can be performed on the
coordinator.

Signed-off-by: Rouven Czerwinski <rouven.czerwinski@linaro.org>
To make ClientSession testing easier, return the token back to the user
when calling create_reservation().

Signed-off-by: Rouven Czerwinski <rouven.czerwinski@linaro.org>
@Emantor
Emantor marked this pull request as draft August 12, 2026 16:35

@asher-pem-arm asher-pem-arm 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.

picked up a few small issues but overall looks good. It would be helpful to document what is planned to be included in this PR/future ones to help us clarify the review scope

Comment thread labgrid/remote/coordinator.py Outdated
parser.add_argument(
"--pystuck-port", metavar="PORT", type=int, default=6666, help="use a different pystuck port than 6666"
)
parser.add_argument("--capabilities", action="store_true", default=False, help="enable using capabilities, which also enforces client identities")

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.

what's the plan for this flag? is this intended as a migration mechanism before full auth?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes, with this flag we indicate that the new identities are required to enable capabilities.

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.

Any reason why we would want a flag? If capabilities are populated by the configured authentication plugin, the coordinator could always enforce them. The default/legacy plugin can preserve current behaviour by granting all capabilities, while secure plugins return restricted sets. With a flag we could get into issues such as auth enabled but capability checks accidentally disabled.

Comment thread labgrid/remote/coordinator.py Outdated
if not identity and cls.use_capabilities == True:
await context.abort(grpc.StatusCode.UNAUTHENTICATED, "Client identity is required when using capabilities")
if identity and (capability not in identity.capabilities):
await context.abort(grpc.StatusCode.PERMISSION_DENIED, f"Capability {req_cap} not in client capabilities {ctx.capabilities}")

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.

don't we want undefined here not PERMISSION_DENIED?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I can't find an undefined error code in https://grpc.io/docs/guides/status-codes/, and PERMISSION_DENIED should be a correct code for a user that wants to run an RPC call for which he does not have the capability.

Comment thread labgrid/remote/coordinator.py Outdated
Comment thread labgrid/remote/coordinator.py Outdated
Comment thread labgrid/remote/coordinator.py Outdated
Comment thread labgrid/remote/coordinator.py Outdated
Apply comments from asher & run ruff.

Signed-off-by: Rouven Czerwinski <rouven.czerwinski@linaro.org>

@asher-pem-arm asher-pem-arm 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.

Can you clarify the intended plugin-wiring boundary? The coordinator, client, and exporter currently instantiate identity interceptors and the server interceptor parses metadata directly into ClientIdentity. Is this deliberately temporary, or should the interceptors accept injected ClientAuthPlugin/ServerAuthPlugin implementations now with plugin discovery and configuration added later?

await context.abort(grpc.StatusCode.UNAUTHENTICATED, "Client identity is required when using capabilities")
if identity and (capability not in identity.capabilities):
await context.abort(
grpc.StatusCode.PERMISSION_DENIED, f"Capability {req_cap} not in client capabilities {ctx.capabilities}"

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.

req_cap and ctx undefined

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.

2 participants