Skip to content

share UFM and NMX-C client-cache rotation logic #5516

Description

@Sinck

Problem

UFM and NMX-C intentionally use the same client-cache lifecycle, but implement it independently:

  • crates/ib-fabric/src/ib/mod.rs caches one UFM REST client per fabric. It invalidates the entry when the endpoint or credentials change, or when certificate material on disk is newer than the cached client.
  • crates/libnmxc/src/lib.rs caches one tonic channel per NMX-C endpoint. It uses the same creation-time and TLS-file-mtime policy to rebuild after certificate rotation.

Both implementations retain a working cached client when TLS files are temporarily missing or unreadable during rotation, recover poisoned cache locks, and rebuild without holding a synchronous lock across asynchronous I/O. The duplicated lifecycle and file-staleness logic can drift as credential and certificate sourcing moves away from Vault under #5200.

The duplication was introduced deliberately by #3256 to fix #3212. Review of the file-backed UFM credential work in #1837 / #5469 identified it as follow-up cleanup rather than expanding that feature.

Desired outcome

Extract a small, protocol-neutral cache/staleness primitive that UFM and NMX-C both use. Keep protocol-specific client construction, cache keys and credential fingerprints, errors, metrics, and log messages in their existing adapters. Prefer sharing only the lifecycle and TLS-material freshness behavior over introducing a broad fabric-manager abstraction.

Acceptance criteria

  • One shared implementation owns cached-entry creation timestamps and the TLS material modification-time policy.
  • UFM and NMX-C both use the shared implementation for lookup, reuse, invalidation, and replacement.
  • UFM continues to rebuild when its resolved endpoint or credentials change.
  • Both clients rebuild when any configured TLS material file is newer than the cached entry.
  • A missing or unreadable TLS file retains the last working cached client rather than forcing a rebuild during an incomplete rotation.
  • The implementation does not hold a synchronous mutex across asynchronous file reads or client construction.
  • Shared table-driven tests cover the common lifecycle; narrow UFM and NMX-C tests prove their protocol-specific keys, fingerprints, and builders remain wired correctly.
  • No credential values, certificate contents, or credential fingerprints are exposed through logs or errors.
  • Credential source precedence, allow_legacy_ufm_fallback, and the UFM CLI mutation policy from feat: Consume UFM credentials from config file/env variables #1837 remain unchanged.

Parent epic: #5200

Metadata

Metadata

Assignees

No one assigned

    Labels

    internalinternal work transparent to end-user

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions