Skip to content

Pass ILoggerFactory to Unobtanium ProxyServer for internal logging#1448

Merged
garrytrinder merged 6 commits intomainfrom
copilot/enable-log-messages
Feb 23, 2026
Merged

Pass ILoggerFactory to Unobtanium ProxyServer for internal logging#1448
garrytrinder merged 6 commits intomainfrom
copilot/enable-log-messages

Conversation

Copy link
Contributor

Copilot AI commented Nov 16, 2025

Unobtanium.Web.Proxy's internal logs (certificate loading, proxy lifecycle) were invisible because ProxyServer was instantiated without a LoggerFactory. This made debugging certificate and proxy initialization issues difficult.

Changes

  • ProxyEngine: Inject ILoggerFactory and pass to ProxyServer constructor via new EnsureProxyServerInitialized() method

    • Thread-safe lazy initialization replaces static constructor initialization
    • ProxyServer remains static for backward compatibility with existing callers
  • CertCommand & ProxyController: Inject ILoggerFactory and call EnsureProxyServerInitialized() before accessing ProxyServer

Unobtanium's internal logs now appear at --log-level Trace:

trce    CertificateManager: LoadOrCreateRootCertificateAsync(True) called
trce    CertificateManager: LoadRootCertificate() called
trce    CertificateManager: Root certificate loaded from file
trce    ProxyServer: StartAsync(changeSystemProxySettings: True) called

Fixes #1410

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • aka.ms
    • Triggering command: /home/REDACTED/work/dev-proxy/dev-proxy/DevProxy/bin/Debug/net9.0/devproxy --help (dns block)
    • Triggering command: /home/REDACTED/work/dev-proxy/dev-proxy/DevProxy/bin/Debug/net9.0/devproxy --log-level Debug --urls-to-watch REDACTED* (dns block)
    • Triggering command: /home/REDACTED/work/dev-proxy/dev-proxy/DevProxy/bin/Debug/net9.0/devproxy cert ensure --log-level Trace (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>Log messages from Unobtanium</issue_title>
<issue_description>> > Here's the point in code where it's loading the certificate: https://github.com/svrooij/unobtanium-web-proxy/blob/5a6d45bcebb55c8e85b75bddc7ffe7f7ebd69d76/src/Unobtanium.Web.Proxy/Certificates/CertificateManager.cs#L609.

I see log calls in that code; can I somehow set a setting, or environment variable that make those log messages appear?

At the moment, the only way would be to update how we instantiate the ProxyServer here:

ProxyServer = new();
and pass the LoggerFactory to the constructor. You'd need to update the code and build Dev Proxy yourself. We're not doing this at the moment in our code at the moment. Sorry for the trouble.

Originally posted by @waldekmastykarz in #1410

We need to ensure that these message are properly displayed in Dev Proxy output. They should be attached to Debug and Trace log levels in Dev Proxy.</issue_description>

<agent_instructions>Pass Dev Proxy LoggerFactory to the constructor. Verify that logging statements from Unobtanium are displayed consistently with other Dev Proxy debug- and trace-level logs.</agent_instructions>

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI changed the title [WIP] Add logger factory to ProxyServer instantiation Pass ILoggerFactory to Unobtanium ProxyServer for internal logging Nov 16, 2025
Copilot AI and others added 3 commits February 22, 2026 13:38
Co-authored-by: waldekmastykarz <11164679+waldekmastykarz@users.noreply.github.com>
@waldekmastykarz waldekmastykarz force-pushed the copilot/enable-log-messages branch from b457356 to a872516 Compare February 22, 2026 12:39
@waldekmastykarz waldekmastykarz marked this pull request as ready for review February 22, 2026 12:45
@waldekmastykarz waldekmastykarz requested a review from a team as a code owner February 22, 2026 12:45
Copilot AI review requested due to automatic review settings February 22, 2026 12:45
@waldekmastykarz
Copy link
Collaborator

Additional changes: macOS certificate trust rewrite

After exposing Unobtanium's logs, we noticed the following errors on every startup on macOS:

fail    Failed to make system trust root certificate for Root\CurrentUser store location. You may need admin rights.
        Exception Details: System.Security.Cryptography.CryptographicException: Access is denied.

This was always happening but was invisible because Unobtanium's logs weren't surfaced.

Root cause

Unobtanium's EnsureRootCertificateAsync calls InstallCertificate(StoreName.Root, StoreLocation.CurrentUser), which uses .NET's X509Store API to open the macOS Root trust store. On macOS, this requires admin privileges and always fails with "Access is denied". This is a .NET platform limitation, not an Unobtanium bug.

Previously, this error was silently swallowed. The actual macOS certificate trust was handled by two bash scripts (trust-cert.sh and remove-cert.sh) that shelled out to security add-trusted-cert/security remove-trusted-cert — a workaround for the broken X509Store path.

Fix

  1. ProxyServer constructor — pass userTrustRootCertificate: RunTime.IsWindows so Unobtanium skips the broken X509Store Root trust attempt on macOS/Linux. Windows behavior is unchanged.

  2. MacCertificateHelper (new) — replaces the bash scripts with C# that exports the certificate from memory to PEM and calls /usr/bin/security directly. This is actually better than the old approach because:

    • The bash scripts used security find-certificate to find the cert in the keychain first — with userTrustRootCertificate: false, the cert is no longer added to the keychain by Unobtanium, so the lookup would have failed
    • Exporting from memory avoids the keychain lookup entirely
    • Better error handling and no external script file dependencies
  3. Removed trust-cert.sh and remove-cert.sh bash scripts and their .csproj references.

  4. Updated CertCommand (cert ensure/cert remove) and FirstRunSetup to use MacCertificateHelper instead of bash scripts. On macOS, cert remove now skips Unobtanium's RemoveTrustedRootCertificate (which would fail the same way) and uses MacCertificateHelper.RemoveTrustedCertificate instead.

Copy link
Contributor

Copilot AI left a comment

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 enables Unobtanium's internal logging by passing ILoggerFactory to the ProxyServer constructor, making certificate and proxy lifecycle logs visible at Trace level. It also refactors certificate management on macOS by replacing bash scripts with C# implementations.

Changes:

  • Refactored ProxyServer initialization from static constructor to lazy thread-safe initialization via EnsureProxyServerInitialized() method to support ILoggerFactory injection
  • Replaced trust-cert.sh and remove-cert.sh bash scripts with MacCertificateHelper C# class for better integration and error handling
  • Updated ProxyEngine, CertCommand, and ProxyController to inject ILoggerFactory and call EnsureProxyServerInitialized() before accessing ProxyServer

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
DevProxy/Proxy/ProxyEngine.cs Added ILoggerFactory injection, implemented thread-safe lazy ProxyServer initialization, replaced bash script call with MacCertificateHelper in FirstRunSetup
DevProxy/Proxy/MacCertificateHelper.cs New helper class for macOS certificate trust/removal operations using /usr/bin/security commands
DevProxy/Commands/CertCommand.cs Added ILoggerFactory injection, updated to use MacCertificateHelper instead of bash scripts
DevProxy/ApiControllers/ProxyController.cs Added ILoggerFactory injection and EnsureProxyServerInitialized call
DevProxy/DevProxy.csproj Removed references to deleted bash scripts
DevProxy/trust-cert.sh Deleted - replaced by MacCertificateHelper.TrustCertificate
DevProxy/remove-cert.sh Deleted - replaced by MacCertificateHelper.RemoveTrustedCertificate

garrytrinder
garrytrinder previously approved these changes Feb 23, 2026
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@garrytrinder garrytrinder merged commit a5cc723 into main Feb 23, 2026
4 checks passed
@waldekmastykarz waldekmastykarz deleted the copilot/enable-log-messages branch February 24, 2026 08:23
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.

Log messages from Unobtanium [BUG]: Can't provide my own rootCert.pfx

4 participants