Skip to content

Add file-backed cert store so CertHelper works on Mac#5257

Merged
DrewScoggins merged 2 commits into
mainfrom
DrewScoggins/certhelper-mac-file-store
Jul 9, 2026
Merged

Add file-backed cert store so CertHelper works on Mac#5257
DrewScoggins merged 2 commits into
mainfrom
DrewScoggins/certhelper-mac-file-store

Conversation

@DrewScoggins

Copy link
Copy Markdown
Member

On macOS the CurrentUser\My X509Store maps to the login Keychain, which cannot export a private key back out without an interactive password prompt. As a result the iphone/Mac queues bypassed CertHelper entirely and relied on hand-provisioned static PFX files that were never rotated.

Introduce an ILocalCertStore abstraction with two implementations:

  • X509LocalCertStore: existing Windows/Linux behavior over the OS store.
  • FileLocalCertStore: persists PFX files (thumbprint-named) in a known directory on Mac, loaded Exportable so no Keychain round-trip is needed.

A factory selects the implementation by OS. LocalCert now loads through the abstraction, and Program.Main rotates via ILocalCertStore.Rotate and exports the in-memory Key Vault certificates to stdout instead of round-tripping through the OS store. common.py's get_certificates now runs CertHelper on all platforms (removing the Mac static-file path), so Mac hosts get the same bootstrap + Key Vault rotation as Linux.

Update LocalCertTests to mock ILocalCertStore and add FileLocalCertStore round-trip tests.

On macOS the CurrentUser\My X509Store maps to the login Keychain, which
cannot export a private key back out without an interactive password
prompt. As a result the iphone/Mac queues bypassed CertHelper entirely
and relied on hand-provisioned static PFX files that were never rotated.

Introduce an ILocalCertStore abstraction with two implementations:
- X509LocalCertStore: existing Windows/Linux behavior over the OS store.
- FileLocalCertStore: persists PFX files (thumbprint-named) in a known
  directory on Mac, loaded Exportable so no Keychain round-trip is needed.

A factory selects the implementation by OS. LocalCert now loads through
the abstraction, and Program.Main rotates via ILocalCertStore.Rotate and
exports the in-memory Key Vault certificates to stdout instead of
round-tripping through the OS store. common.py's get_certificates now
runs CertHelper on all platforms (removing the Mac static-file path), so
Mac hosts get the same bootstrap + Key Vault rotation as Linux.

Update LocalCertTests to mock ILocalCertStore and add FileLocalCertStore
round-trip tests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 9, 2026 19:47

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 updates CertHelper to work reliably on macOS by introducing a local certificate storage abstraction that can use a file-backed PFX directory on Mac (avoiding Keychain private-key export prompts), while keeping the existing OS-store behavior on Windows/Linux. It also unifies certificate retrieval in the perf scripts so CertHelper is used on all platforms, and updates/adds tests accordingly.

Changes:

  • Add ILocalCertStore + factory with X509LocalCertStore (OS store) and FileLocalCertStore (PFX files).
  • Update CertHelper (LocalCert, Program.Main) to load/rotate/export via ILocalCertStore, exporting Key Vault certs directly to stdout.
  • Update common.py to always invoke CertHelper (removing the macOS static PFX read path) and expand test coverage for the new file-backed store.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/tools/CertHelperTests/LocalCertTests.cs Update tests to mock ILocalCertStore via GetCertificates() instead of IX509Store.Certificates.
src/tools/CertHelperTests/FileLocalCertStoreTests.cs Add round-trip tests for the new file-backed cert store (write/reload/replace/export).
src/tools/CertHelper/Program.cs Use ILocalCertStore for rotation and export Key Vault certs directly to stdout with fallback to local store.
src/tools/CertHelper/LocalCert.cs Load local certificates via ILocalCertStore instead of directly through IX509Store.
src/tools/CertHelper/ILocalCertStore.cs Introduce the abstraction, factory, and both store implementations (OS-backed + file-backed).
scripts/performance/common.py Always run CertHelper to retrieve certificates across all platforms.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/tools/CertHelper/ILocalCertStore.cs
Comment thread src/tools/CertHelper/ILocalCertStore.cs
Comment thread src/tools/CertHelper/ILocalCertStore.cs
Comment thread src/tools/CertHelper/ILocalCertStore.cs
LoopedBard3
LoopedBard3 previously approved these changes Jul 9, 2026

@LoopedBard3 LoopedBard3 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks good, copilot may have some good feedback though.

- X509LocalCertStore now opens the store read-write by default and no
  longer re-opens/closes it in Rotate, so rotation works reliably on
  Windows/Linux and reads remain valid.
- FileLocalCertStore restricts written PFX files to owner read/write
  (0600) on macOS so the private keys are not left world-readable.

Note: the reviewer's suggestion to load PFXs with EphemeralKeySet is not
applied because EphemeralKeySet throws PlatformNotSupportedException on
macOS, which is the only platform that uses FileLocalCertStore.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 9, 2026 22:40

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

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Comment thread src/tools/CertHelper/ILocalCertStore.cs
Comment thread src/tools/CertHelper/ILocalCertStore.cs
@DrewScoggins DrewScoggins enabled auto-merge (squash) July 9, 2026 23:05
@DrewScoggins DrewScoggins disabled auto-merge July 9, 2026 23:35
@DrewScoggins DrewScoggins merged commit 7c16da2 into main Jul 9, 2026
73 of 76 checks passed
@DrewScoggins DrewScoggins deleted the DrewScoggins/certhelper-mac-file-store branch July 9, 2026 23:35
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.

3 participants