natemcmaster/LettuceEncrypt

Null reference when doing unsupported wildcards, workaround to do multi-site wildcard ssl

JessicaMulein opened this issue · 4 comments

Describe the bug
When trying to use LettuceEncrypt for Wildcard SSL, we receive an object not set error when doing unsupported wildcards.

Initially I thought I'd have to do DNS manual, but certbot worked fine. The comments below contain a workaround and provide a means to have a little more control over the certs- implements a cert store to pull the certs off a docker volume.

To Reproduce
Steps to reproduce the behavior:

  1. Using nuget version of the library '1.1.1'
  2. added the .UseLettuceEncrypt()
  3. using config file here: https://github.com/The-Revolution-Network/BrightChain.API/blob/main/appsettings.Production.json
  4. See error below

Expected behavior
Either an error indicating unsupported behavior, or implement whatever mechanism certbot is using.

Additional context
http/https are definitely through the firewall and http redirect works while the container is running.

C:\Users\JessicaMulein\source\repos\The-Revolution-Network\BrightChain\src\BrightChain.API>docker run --rm -itd --name=brightchainapi --privileged -p 80:80 -p 443:443 -e ASPNETCORE_URLS="https://+;http://+" -e ASPNETCORE_HTTPS_PORT=443 -e DOMAIN_NAME=brightchain.net -e USE_STAGING_SERVER=false brightchainapi:splash
45a28aafd0dbd830865e7950e85598a4a7e93169282f200f03a39d2b48a9abe4

C:\Users\JessicaMulein\source\repos\The-Revolution-Network\BrightChain\src\BrightChain.API>docker logs -f 45a28aafd0dbd830865e7950e85598a4a7e93169282f200f03a39d2b48a9abe4
{"EventId":60,"LogLevel":"Warning","Category":"Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository","Message":"Storing keys in a directory \u0027/root/.aspnet/DataProtection-Keys\u0027 that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed.","State":{"Message":"Storing keys in a directory \u0027/root/.aspnet/DataProtection-Keys\u0027 that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed.","path":"/root/.aspnet/DataProtection-Keys","{OriginalFormat}":"Storing keys in a directory \u0027{path}\u0027 that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed."}}
{"EventId":35,"LogLevel":"Warning","Category":"Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager","Message":"No XML encryptor configured. Key {90a2cde1-84ac-4c6b-a68c-ee066f1be1d8} may be persisted to storage in unencrypted form.","State":{"Message":"No XML encryptor configured. Key {90a2cde1-84ac-4c6b-a68c-ee066f1be1d8} may be persisted to storage in unencrypted form.","KeyId":"90a2cde1-84ac-4c6b-a68c-ee066f1be1d8","{OriginalFormat}":"No XML encryptor configured. Key {KeyId:B} may be persisted to storage in unencrypted form."}}
{"EventId":0,"LogLevel":"Trace","Category":"LettuceEncrypt.Internal.AcmeCertificateLoader","Message":"ACME state transition: moving to ServerStartupState","State":{"Message":"ACME state transition: moving to ServerStartupState","stateName":"ServerStartupState","{OriginalFormat}":"ACME state transition: moving to {stateName}"}}
{"EventId":0,"LogLevel":"Trace","Category":"LettuceEncrypt.Internal.AcmeCertificateLoader","Message":"ACME state transition: moving to BeginCertificateCreationState","State":{"Message":"ACME state transition: moving to BeginCertificateCreationState","stateName":"BeginCertificateCreationState","{OriginalFormat}":"ACME state transition: moving to {stateName}"}}
{"EventId":0,"LogLevel":"Trace","Category":"LettuceEncrypt.Internal.AcmeCertificateFactory","Message":"Looking for account information in /app/accounts/acme-v02.api.letsencrypt.org/directory","State":{"Message":"Looking for account information in /app/accounts/acme-v02.api.letsencrypt.org/directory","path":"/app/accounts/acme-v02.api.letsencrypt.org/directory","{OriginalFormat}":"Looking for account information in {path}"}}
{"EventId":0,"LogLevel":"Debug","Category":"LettuceEncrypt.Internal.AcmeCertificateFactory","Message":"Could not find account information in /app/accounts/acme-v02.api.letsencrypt.org/directory","State":{"Message":"Could not find account information in /app/accounts/acme-v02.api.letsencrypt.org/directory","path":"/app/accounts/acme-v02.api.letsencrypt.org/directory","{OriginalFormat}":"Could not find account information in {path}"}}
{"EventId":0,"LogLevel":"Information","Category":"LettuceEncrypt.Internal.AcmeClient","Message":"Using certificate authority https://acme-v02.api.letsencrypt.org/directory","State":{"Message":"Using certificate authority https://acme-v02.api.letsencrypt.org/directory","directoryUri":"https://acme-v02.api.letsencrypt.org/directory","{OriginalFormat}":"Using certificate authority {directoryUri}"}}
{"EventId":0,"LogLevel":"Trace","Category":"LettuceEncrypt.Internal.AcmeClient","Message":"ACMEv2 action: FetchTOS","State":{"Message":"ACMEv2 action: FetchTOS","name":"FetchTOS","{OriginalFormat}":"ACMEv2 action: {name}"}}
{"EventId":14,"LogLevel":"Information","Category":"Microsoft.Hosting.Lifetime","Message":"Now listening on: https://[::]:443","State":{"Message":"Now listening on: https://[::]:443","address":"https://[::]:443","{OriginalFormat}":"Now listening on: {address}"}}
{"EventId":14,"LogLevel":"Information","Category":"Microsoft.Hosting.Lifetime","Message":"Now listening on: http://[::]:80","State":{"Message":"Now listening on: http://[::]:80","address":"http://[::]:80","{OriginalFormat}":"Now listening on: {address}"}}
{"EventId":0,"LogLevel":"Information","Category":"Microsoft.Hosting.Lifetime","Message":"Application started. Press Ctrl\u002BC to shut down.","State":{"Message":"Application started. Press Ctrl\u002BC to shut down.","{OriginalFormat}":"Application started. Press Ctrl\u002BC to shut down."}}
{"EventId":0,"LogLevel":"Information","Category":"Microsoft.Hosting.Lifetime","Message":"Hosting environment: Production","State":{"Message":"Hosting environment: Production","envName":"Production","{OriginalFormat}":"Hosting environment: {envName}"}}
{"EventId":0,"LogLevel":"Information","Category":"Microsoft.Hosting.Lifetime","Message":"Content root path: /app","State":{"Message":"Content root path: /app","contentRoot":"/app","{OriginalFormat}":"Content root path: {contentRoot}"}}
{"EventId":0,"LogLevel":"Trace","Category":"LettuceEncrypt.Internal.TermsOfServiceChecker","Message":"Terms of service has been accepted per configuration options","State":{"Message":"Terms of service has been accepted per configuration options","{OriginalFormat}":"Terms of service has been accepted per configuration options"}}
{"EventId":0,"LogLevel":"Information","Category":"LettuceEncrypt.Internal.AcmeCertificateFactory","Message":"Creating new account for viva@therevolution.network","State":{"Message":"Creating new account for viva@therevolution.network","email":"viva@therevolution.network","{OriginalFormat}":"Creating new account for {email}"}}
{"EventId":0,"LogLevel":"Trace","Category":"LettuceEncrypt.Internal.AcmeClient","Message":"ACMEv2 action: NewAccount","State":{"Message":"ACMEv2 action: NewAccount","name":"NewAccount","{OriginalFormat}":"ACMEv2 action: {name}"}}
{"EventId":0,"LogLevel":"Trace","Category":"LettuceEncrypt.Internal.AcmeCertificateFactory","Message":"Saving account information to /app/accounts/acme-v02.api.letsencrypt.org/directory/197664990.json","State":{"Message":"Saving account information to /app/accounts/acme-v02.api.letsencrypt.org/directory/197664990.json","path":"/app/accounts/acme-v02.api.letsencrypt.org/directory/197664990.json","{OriginalFormat}":"Saving account information to {path}"}}
{"EventId":0,"LogLevel":"Debug","Category":"LettuceEncrypt.Internal.AcmeCertificateFactory","Message":"Saved account information to /app/accounts/acme-v02.api.letsencrypt.org/directory/197664990.json","State":{"Message":"Saved account information to /app/accounts/acme-v02.api.letsencrypt.org/directory/197664990.json","path":"/app/accounts/acme-v02.api.letsencrypt.org/directory/197664990.json","{OriginalFormat}":"Saved account information to {path}"}}
{"EventId":0,"LogLevel":"Information","Category":"LettuceEncrypt.Internal.AcmeStates.ServerStartupState","Message":"Using account 197664990","State":{"Message":"Using account 197664990","accountId":197664990,"{OriginalFormat}":"Using account {accountId}"}}
{"EventId":0,"LogLevel":"Information","Category":"LettuceEncrypt.Internal.AcmeStates.ServerStartupState","Message":"Creating certificate for *.brightchain.net,*.therevolution.network","State":{"Message":"Creating certificate for *.brightchain.net,*.therevolution.network","hostname":"*.brightchain.net,*.therevolution.network","{OriginalFormat}":"Creating certificate for {hostname}"}}
{"EventId":0,"LogLevel":"Trace","Category":"LettuceEncrypt.Internal.AcmeClient","Message":"ACMEv2 action: FetchOrderList","State":{"Message":"ACMEv2 action: FetchOrderList","name":"FetchOrderList","{OriginalFormat}":"ACMEv2 action: {name}"}}
{"EventId":0,"LogLevel":"Trace","Category":"LettuceEncrypt.Internal.AcmeClient","Message":"ACMEv2 action: FetchOrderDetails, (null)","State":{"Message":"ACMEv2 action: FetchOrderDetails, (null)","name":"FetchOrderDetails","resource":null,"{OriginalFormat}":"ACMEv2 action: {name}, {resource}"}}
{"EventId":0,"LogLevel":"Debug","Category":"LettuceEncrypt.Internal.AcmeCertificateFactory","Message":"Creating new order for a certificate","State":{"Message":"Creating new order for a certificate","{OriginalFormat}":"Creating new order for a certificate"}}
{"EventId":0,"LogLevel":"Trace","Category":"LettuceEncrypt.Internal.AcmeClient","Message":"ACMEv2 action: NewOrder","State":{"Message":"ACMEv2 action: NewOrder","name":"NewOrder","{OriginalFormat}":"ACMEv2 action: {name}"}}
{"EventId":0,"LogLevel":"Trace","Category":"LettuceEncrypt.Internal.AcmeClient","Message":"ACMEv2 action: FetchAuthorizations, https://acme-v02.api.letsencrypt.org/acme/order/197664990/23853703700","State":{"Message":"ACMEv2 action: FetchAuthorizations, https://acme-v02.api.letsencrypt.org/acme/order/197664990/23853703700","name":"FetchAuthorizations","resource":"https://acme-v02.api.letsencrypt.org/acme/order/197664990/23853703700","{OriginalFormat}":"ACMEv2 action: {name}, {resource}"}}
{"EventId":0,"LogLevel":"Trace","Category":"LettuceEncrypt.Internal.AcmeClient","Message":"ACMEv2 action: FetchAuthorizationDetails, https://acme-v02.api.letsencrypt.org/acme/authz-v3/30222836470","State":{"Message":"ACMEv2 action: FetchAuthorizationDetails, https://acme-v02.api.letsencrypt.org/acme/authz-v3/30222836470","name":"FetchAuthorizationDetails","resource":"https://acme-v02.api.letsencrypt.org/acme/authz-v3/30222836470","{OriginalFormat}":"ACMEv2 action: {name}, {resource}"}}
{"EventId":0,"LogLevel":"Trace","Category":"LettuceEncrypt.Internal.AcmeClient","Message":"ACMEv2 action: FetchAuthorizationDetails, https://acme-v02.api.letsencrypt.org/acme/authz-v3/30222836480","State":{"Message":"ACMEv2 action: FetchAuthorizationDetails, https://acme-v02.api.letsencrypt.org/acme/authz-v3/30222836480","name":"FetchAuthorizationDetails","resource":"https://acme-v02.api.letsencrypt.org/acme/authz-v3/30222836480","{OriginalFormat}":"ACMEv2 action: {name}, {resource}"}}
{"EventId":0,"LogLevel":"Debug","Category":"LettuceEncrypt.Internal.AcmeCertificateFactory","Message":"Requesting authorization to create certificate for brightchain.net","State":{"Message":"Requesting authorization to create certificate for brightchain.net","domainName":"brightchain.net","{OriginalFormat}":"Requesting authorization to create certificate for {domainName}"}}
{"EventId":0,"LogLevel":"Trace","Category":"LettuceEncrypt.Internal.AcmeClient","Message":"ACMEv2 action: CreateChallenge, https://acme-v02.api.letsencrypt.org/acme/authz-v3/30222836470","State":{"Message":"ACMEv2 action: CreateChallenge, https://acme-v02.api.letsencrypt.org/acme/authz-v3/30222836470","name":"CreateChallenge","resource":"https://acme-v02.api.letsencrypt.org/acme/authz-v3/30222836470","{OriginalFormat}":"ACMEv2 action: {name}, {resource}"}}
{"EventId":0,"LogLevel":"Debug","Category":"LettuceEncrypt.Internal.AcmeCertificateFactory","Message":"Requesting authorization to create certificate for therevolution.network","State":{"Message":"Requesting authorization to create certificate for therevolution.network","domainName":"therevolution.network","{OriginalFormat}":"Requesting authorization to create certificate for {domainName}"}}
{"EventId":0,"LogLevel":"Trace","Category":"LettuceEncrypt.Internal.AcmeClient","Message":"ACMEv2 action: CreateChallenge, https://acme-v02.api.letsencrypt.org/acme/authz-v3/30222836480","State":{"Message":"ACMEv2 action: CreateChallenge, https://acme-v02.api.letsencrypt.org/acme/authz-v3/30222836480","name":"CreateChallenge","resource":"https://acme-v02.api.letsencrypt.org/acme/authz-v3/30222836480","{OriginalFormat}":"ACMEv2 action: {name}, {resource}"}}
{"EventId":0,"LogLevel":"Trace","Category":"LettuceEncrypt.Internal.TlsAlpnChallengeResponder","Message":"Clearing ALPN cert for brightchain.net","State":{"Message":"Clearing ALPN cert for brightchain.net","domainName":"brightchain.net","{OriginalFormat}":"Clearing ALPN cert for {domainName}"}}
{"EventId":0,"LogLevel":"Debug","Category":"LettuceEncrypt.Internal.AcmeCertificateFactory","Message":"Validation with TlsAlpn01DomainValidator failed with error: Object reference not set to an instance of an object.","Exception":"System.NullReferenceException: Object reference not set to an instance of an object.    at LettuceEncrypt.Internal.TlsAlpn01DomainValidator.PrepareTlsAlpnChallengeResponseAsync(IAuthorizationContext authorizationContext, String domainName, CancellationToken cancellationToken) in LettuceEncrypt.dll:token 0x6000077\u002B0x9e    at LettuceEncrypt.Internal.TlsAlpn01DomainValidator.ValidateOwnershipAsync(IAuthorizationContext authzContext, CancellationToken cancellationToken) in LettuceEncrypt.dll:token 0x6000076\u002B0x83    at LettuceEncrypt.Internal.AcmeCertificateFactory.ValidateDomainOwnershipAsync(IAuthorizationContext authorizationContext, CancellationToken cancellationToken) in LettuceEncrypt.dll:token 0x6000028\u002B0x256","State":{"Message":"Validation with TlsAlpn01DomainValidator failed with error: Object reference not set to an instance of an object.","validatorType":"TlsAlpn01DomainValidator","error":"Object reference not set to an instance of an object.","{OriginalFormat}":"Validation with {validatorType} failed with error: {error}"}}
{"EventId":0,"LogLevel":"Trace","Category":"LettuceEncrypt.Internal.TlsAlpnChallengeResponder","Message":"Clearing ALPN cert for therevolution.network","State":{"Message":"Clearing ALPN cert for therevolution.network","domainName":"therevolution.network","{OriginalFormat}":"Clearing ALPN cert for {domainName}"}}
{"EventId":0,"LogLevel":"Debug","Category":"LettuceEncrypt.Internal.AcmeCertificateFactory","Message":"Validation with TlsAlpn01DomainValidator failed with error: Object reference not set to an instance of an object.","Exception":"System.NullReferenceException: Object reference not set to an instance of an object.    at LettuceEncrypt.Internal.TlsAlpn01DomainValidator.PrepareTlsAlpnChallengeResponseAsync(IAuthorizationContext authorizationContext, String domainName, CancellationToken cancellationToken) in LettuceEncrypt.dll:token 0x6000077\u002B0x9e    at LettuceEncrypt.Internal.TlsAlpn01DomainValidator.ValidateOwnershipAsync(IAuthorizationContext authzContext, CancellationToken cancellationToken) in LettuceEncrypt.dll:token 0x6000076\u002B0x83    at LettuceEncrypt.Internal.AcmeCertificateFactory.ValidateDomainOwnershipAsync(IAuthorizationContext authorizationContext, CancellationToken cancellationToken) in LettuceEncrypt.dll:token 0x6000028\u002B0x256","State":{"Message":"Validation with TlsAlpn01DomainValidator failed with error: Object reference not set to an instance of an object.","validatorType":"TlsAlpn01DomainValidator","error":"Object reference not set to an instance of an object.","{OriginalFormat}":"Validation with {validatorType} failed with error: {error}"}}
{"EventId":0,"LogLevel":"Error","Category":"LettuceEncrypt.Internal.AcmeStates.ServerStartupState","Message":"Failed to automatically create a certificate for *.brightchain.net","Exception":"System.InvalidOperationException: Failed to validate ownership of domainName \u0027brightchain.net\u0027    at LettuceEncrypt.Internal.AcmeCertificateFactory.ValidateDomainOwnershipAsync(IAuthorizationContext authorizationContext, CancellationToken cancellationToken) in LettuceEncrypt.dll:token 0x6000028\u002B0x2f0    at LettuceEncrypt.Internal.AcmeCertificateFactory.CreateCertificateAsync(CancellationToken cancellationToken) in LettuceEncrypt.dll:token 0x6000026\u002B0x3d0    at LettuceEncrypt.Internal.AcmeStates.BeginCertificateCreationState.MoveNextAsync(CancellationToken cancellationToken) in LettuceEncrypt.dll:token 0x60000b2\u002B0x154","State":{"Message":"Failed to automatically create a certificate for *.brightchain.net","hostname":"*.brightchain.net","{OriginalFormat}":"Failed to automatically create a certificate for {hostname}"}}
{"EventId":0,"LogLevel":"Error","Category":"LettuceEncrypt.Internal.AcmeCertificateLoader","Message":"ACME state machine encountered unhandled error","Exception":"System.InvalidOperationException: Failed to validate ownership of domainName \u0027brightchain.net\u0027    at LettuceEncrypt.Internal.AcmeCertificateFactory.ValidateDomainOwnershipAsync(IAuthorizationContext authorizationContext, CancellationToken cancellationToken) in LettuceEncrypt.dll:token 0x6000028\u002B0x2f0    at LettuceEncrypt.Internal.AcmeCertificateFactory.CreateCertificateAsync(CancellationToken cancellationToken) in LettuceEncrypt.dll:token 0x6000026\u002B0x3d0    at LettuceEncrypt.Internal.AcmeStates.BeginCertificateCreationState.MoveNextAsync(CancellationToken cancellationToken) in LettuceEncrypt.dll:token 0x60000b2\u002B0x154    at LettuceEncrypt.Internal.AcmeCertificateLoader.ExecuteAsync(CancellationToken stoppingToken) in LettuceEncrypt.dll:token 0x600002c\u002B0x15d","State":{"Message":"ACME state machine encountered unhandled error","{OriginalFormat}":"ACME state machine encountered unhandled error"}}

Well. It would seem (#1) my issue is using wildcard certs with LettuceEncrypt. Neither Http01 nor Tls methods support wildcards according to the letsencrypt challenge types page. DNS-01 is the only way, and that needs to be done interactively.

I am not closing the ticket as there does seem to at least be a bug not detecting this unsupported state and the fact that there seems to not exist any solution for this. I understand why DNS-01 isn't supported for automated, but I think we should be able to use a manual client to do that and then use a docker volume/mount to bring the saved state in?

Here's my workaround:

Do certbot manually, let docker create a couple containers:

$ docker run -it --rm -p 443:443 -p 80:80 --name certbot  -v https:/etc/letsencrypt -v varhttps:/var/lib/letsencrypt certbot/certbot certonly --manual
{do dns steps}

$ docker run -it --rm -p 443:443 -p 80:80 --name certbot  -v https:/etc/letsencrypt -v varhttps:/var/lib/letsencrypt certbot/certbot certonly --standalone
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Please enter the domain name(s) you would like on your certificate (comma and/or
space separated) (Enter 'c' to cancel): *.brightchain.net,brightchain.net,*.therevolution.network,therevolution.network
Requesting a certificate for *.brightchain.net and 3 more domains

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/brightchain.net/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/brightchain.net/privkey.pem
This certificate expires on 2021-12-11.
These files will be updated when the certificate renews.

NEXT STEPS:
- The certificate will need to be renewed before it expires. Certbot can automatically renew the certificate in the background, but you may need to take steps to enable that functionality. See https://certbot.org/renewal-setup for instructions.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
 * Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
 * Donating to EFF:                    https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Add a LettuceEncryptStore as I did here and mount the volumes. Also see the changes to appSettings
https://github.com/The-Revolution-Network/BrightChain.API/commit/2fb7182c438a87771976a17dfb2fe4fb016988bb

Run container:

C:\Users\JessicaMulein\source\repos\The-Revolution-Network\BrightChain\src\BrightChain.API>docker run --rm -itd --name=brightchainapi -v https:/etc/letsencrypt -v varhttps:/var/lib/letsencrypt --privileged -p 80:80 -p 443:443 -e ASPNETCORE_URLS="https://+;http://+" -e ASPNETCORE_HTTPS_PORT=443 -e DOMAIN_NAME=brightchain.net -e USE_STAGING_SERVER=false brightchainapi:splash
ea3db065b177d53c4ebda48ae59011dc5880fc86cdd29b888ef7d01cb4045a9f

C:\Users\JessicaMulein\source\repos\The-Revolution-Network\BrightChain\src\BrightChain.API>docker logs -f brightchainapi
{"EventId":60,"LogLevel":"Warning","Category":"Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository","Message":"Storing keys in a directory \u0027/root/.aspnet/DataProtection-Keys\u0027 that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed.","State":{"Message":"Storing keys in a directory \u0027/root/.aspnet/DataProtection-Keys\u0027 that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed.","path":"/root/.aspnet/DataProtection-Keys","{OriginalFormat}":"Storing keys in a directory \u0027{path}\u0027 that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed."}}
{"EventId":35,"LogLevel":"Warning","Category":"Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager","Message":"No XML encryptor configured. Key {948b6bc3-25ee-4775-bacc-d30d1f2afb8d} may be persisted to storage in unencrypted form.","State":{"Message":"No XML encryptor configured. Key {948b6bc3-25ee-4775-bacc-d30d1f2afb8d} may be persisted to storage in unencrypted form.","KeyId":"948b6bc3-25ee-4775-bacc-d30d1f2afb8d","{OriginalFormat}":"No XML encryptor configured. Key {KeyId:B} may be persisted to storage in unencrypted form."}}
{"EventId":0,"LogLevel":"Trace","Category":"LettuceEncrypt.Internal.CertificateSelector","Message":"Successfully tested certificate chain for *.brightchain.net","State":{"Message":"Successfully tested certificate chain for *.brightchain.net","commonName":"*.brightchain.net","{OriginalFormat}":"Successfully tested certificate chain for {commonName}"}}
{"EventId":0,"LogLevel":"Trace","Category":"LettuceEncrypt.Internal.AcmeCertificateLoader","Message":"ACME state transition: moving to ServerStartupState","State":{"Message":"ACME state transition: moving to ServerStartupState","stateName":"ServerStartupState","{OriginalFormat}":"ACME state transition: moving to {stateName}"}}
{"EventId":0,"LogLevel":"Debug","Category":"LettuceEncrypt.Internal.AcmeStates.ServerStartupState","Message":"Certificate for *.brightchain.net already found.","State":{"Message":"Certificate for *.brightchain.net already found.","domainNames":"*.brightchain.net","{OriginalFormat}":"Certificate for {domainNames} already found."}}
{"EventId":0,"LogLevel":"Trace","Category":"LettuceEncrypt.Internal.AcmeCertificateLoader","Message":"ACME state transition: moving to CheckForRenewalState","State":{"Message":"ACME state transition: moving to CheckForRenewalState","stateName":"CheckForRenewalState","{OriginalFormat}":"ACME state transition: moving to {stateName}"}}
{"EventId":0,"LogLevel":"Debug","Category":"LettuceEncrypt.Internal.AcmeStates.CheckForRenewalState","Message":"Checking certificates\u0027 renewals for *.brightchain.net, brightchain.net, *.therevolution.network, therevolution.network","State":{"Message":"Checking certificates\u0027 renewals for *.brightchain.net, brightchain.net, *.therevolution.network, therevolution.network","hostname":"*.brightchain.net, brightchain.net, *.therevolution.network, therevolution.network","{OriginalFormat}":"Checking certificates\u0027 renewals for {hostname}"}}
{"EventId":14,"LogLevel":"Information","Category":"Microsoft.Hosting.Lifetime","Message":"Now listening on: https://[::]:443","State":{"Message":"Now listening on: https://[::]:443","address":"https://[::]:443","{OriginalFormat}":"Now listening on: {address}"}}
{"EventId":14,"LogLevel":"Information","Category":"Microsoft.Hosting.Lifetime","Message":"Now listening on: http://[::]:80","State":{"Message":"Now listening on: http://[::]:80","address":"http://[::]:80","{OriginalFormat}":"Now listening on: {address}"}}
{"EventId":0,"LogLevel":"Information","Category":"Microsoft.Hosting.Lifetime","Message":"Application started. Press Ctrl\u002BC to shut down.","State":{"Message":"Application started. Press Ctrl\u002BC to shut down.","{OriginalFormat}":"Application started. Press Ctrl\u002BC to shut down."}}
{"EventId":0,"LogLevel":"Information","Category":"Microsoft.Hosting.Lifetime","Message":"Hosting environment: Production","State":{"Message":"Hosting environment: Production","envName":"Production","{OriginalFormat}":"Hosting environment: {envName}"}}
{"EventId":0,"LogLevel":"Information","Category":"Microsoft.Hosting.Lifetime","Message":"Content root path: /app","State":{"Message":"Content root path: /app","contentRoot":"/app","{OriginalFormat}":"Content root path: {contentRoot}"}}
{"EventId":0,"LogLevel":"Information","Category":"BrightBlockService","Message":"\u003CBrightBlockService\u003E: logging initialized","State":{"Message":"\u003CBrightBlockService\u003E: logging initialized","{OriginalFormat}":"\u003CBrightBlockService\u003E: logging initialized"}}
{"EventId":0,"LogLevel":"Information","Category":"BrightBlockService","Message":"\u003CBrightBlockService\u003E: caches initialized","State":{"Message":"\u003CBrightBlockService\u003E: caches initialized","{OriginalFormat}":"\u003CBrightBlockService\u003E: caches initialized"}}

I've opened #221 to raise an error to make this clearer.

I'm open to supporting wildcard domains if someone wants to help implement #1. But it's not something I'm actively working on.