Skip to content

MASQUE: a grant the authority renews after core stopped it leaves the adopted attachment refused #1236

Open

Description

@privateip

What happens

A connector's authorization (its EdgeService) is valid until validUntil, at most 28 s after the last authorize or refresh. Core and galactic-edge stop it 2 s (MaxSkew) before that, and core refuses the connector's attachment with GrantExpired. The grant authority, however, treats the incarnation as live until validUntil itself.

If the connector's next request arrives inside that 2 s window, the authority renews the incarnation in place, so the service's validUntil moves forward under the same UID. Core does not re-admit the attachment it already refused, and the provider adapter fails each request at once with attachment_failed (GrantExpired) on that refused attachment instead of replacing it. The connector gets 503 on every request until the attachment goes away, about 30 s in the lab, although its credential and authorization are valid throughout.

How it was seen

In the containerlab gVPC lab, with the MASQUE service and grant authority from config/masque:

  1. Two connectors forward through one provider pod.
  2. The provider process is killed with SIGKILL. The kubelet restarts it in the same pod, and the new process adopts the pod's attachments, then waits about 17 s for the old process's lease to expire.
  3. One connector's next request reached the authority 1 to 2 s before its incarnation's validUntil.

The provider then logged, every 2 s for 31 s:

admission refused outcome=attachment_failed vpc=ns20/20 error="masque: connector unavailable: connector <id>: attachment ea-<pod>-<service> refused: GrantExpired: grant <service> expired at <validUntil>"

The EdgeService kept its UID across these requests. The connector was served again only after the attachment was requested anew.

The window is narrow and depends on timing: in five runs of the same row it happened once. It is not specific to a process restart. Any connector whose next request lands within MaxSkew of its idle incarnation's validUntil can hit it.

Expected

A request whose authorization the authority renews is admitted, or the authority refuses to renew an incarnation core has already stopped and issues a new one. Either way the connector should not get 503s for the attachment's idle period while its grant is valid.

Possible fixes:

  • The authority treats an incarnation within MaxSkew of validUntil as expired: it retires it and issues a successor, as it does after validUntil.
  • The adapter deletes an attachment core refused with GrantExpired and requests a new one when a renewed grant arrives.

Related

Found while running the MASQUE service lab rows for #980 and #976. The lab's process-restart row reconnects as soon as the new process holds its lease, so it stays clear of this window.

Activity

  1. added theissue type on Oct 29, 2026
  2. privateip commented on Oct 29, 2026

    @privateip
    CollaboratorAuthor

    A second, deterministic way to hit this in the lab: stop the grant authority's process while a connector forwards. The request ends at the grant's deadline, the authority's sweep is stopped too, so the incarnation is never retired. Once the authority resumes, it renews the same incarnation in place, and every request of the connector for the next 31 s got attachment_failed with GrantExpired on the old attachment, until the adapter deleted it and requested a new one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Fields

    Priority

    None yet

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions