Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom launchSettings.json profile causes "Unable to configure HTTPS endpoint. No server certificate was specified" #33220

Closed
Kla3mus opened this issue Jun 2, 2021 · 9 comments
Labels
area-commandlinetools Includes: Command line tools, dotnet-dev-certs, dotnet-user-jwts, and OpenAPI docker feature-devcerts ✔️ Resolution: Answered Resolved because the question asked by the original author has been answered. question Status: Resolved

Comments

@Kla3mus
Copy link

Kla3mus commented Jun 2, 2021

Description

When creating a new standard blazor serverside (with docker) project, and adding the following to launchSettings.json:

"DockerTest": {
      "commandName": "Docker",
      "launchBrowser": true,
      "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}",
      "publishAllPorts": true,
      "useSSL": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "TEST"
      }
    }

I basically copied the entry for Docker, renamed Docker to DockerTest and added the environmentVariables

Then selecting that particular profile and run it, I get the following exception:
image

Happens both in Chrome and Firefox

App runs fine if I use the default Docker profile.

I tried to do what the exception said; and this is what the developer console spit out:
image

Configuration

I'm running .net 5.0.300 on windows 10, 20H2 build 19042.985
Visual Studio 2019 - 16,10,0

System.InvalidOperationException
HResult=0x80131509
Message=Unable to configure HTTPS endpoint. No server certificate was specified, and the default developer certificate could not be found or is out of date.
To generate a developer certificate run 'dotnet dev-certs https'. To trust the certificate (Windows and macOS only) run 'dotnet dev-certs https --trust'.
For more information on configuring HTTPS see https://go.microsoft.com/fwlink/?linkid=848054.
Source=Microsoft.AspNetCore.Server.Kestrel.Core
StackTrace:
at Microsoft.AspNetCore.Hosting.ListenOptionsHttpsExtensions.UseHttps(ListenOptions listenOptions, Action1 configureOptions) at Microsoft.AspNetCore.Hosting.ListenOptionsHttpsExtensions.UseHttps(ListenOptions listenOptions) at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.AddressesStrategy.<BindAsync>d__2.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult() at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.<BindAsync>d__0.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult() at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.<BindAsync>d__32.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult() at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.<StartAsync>d__291.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Microsoft.AspNetCore.Hosting.GenericWebHostService.d__31.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult()
at Microsoft.Extensions.Hosting.Internal.Host.d__9.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult()
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.d__4.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.d__4.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.Run(IHost host)
at Admin.Program.Main(String[] args) in C:\Devops\ST-Test\Admin\Program.cs:line 16

This exception was originally thrown at this call stack:
Microsoft.AspNetCore.Hosting.ListenOptionsHttpsExtensions.UseHttps(Microsoft.AspNetCore.Server.Kestrel.Core.ListenOptions, System.Action<Microsoft.AspNetCore.Server.Kestrel.Https.HttpsConnectionAdapterOptions>)
Microsoft.AspNetCore.Hosting.ListenOptionsHttpsExtensions.UseHttps(Microsoft.AspNetCore.Server.Kestrel.Core.ListenOptions)
Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.AddressesStrategy.BindAsync(Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBindContext)
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(System.Threading.Tasks.Task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(System.Threading.Tasks.Task)
System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult()
Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.BindAsync(System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Server.Kestrel.Core.ListenOptions>, Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBindContext)
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(System.Threading.Tasks.Task)
...
[Call Stack Truncated]

@ManickaP
Copy link
Member

ManickaP commented Jun 2, 2021

I did some experimenting and since you're switching the environment to one that is not from the predefined 3: Development, Staging, Production; it's somehow not able to pick up the trusted cert. I assume there's some piece of configuration that needs to be done for the new environment.

Is using your custom environment something that's necessary for you? I assume that if you switch back to "Development" it will work.

@Pilchie My knowledge here is lacking. Is this something unsupported? Or is there anything the customer can do to make it work?

@Pilchie
Copy link
Member

Pilchie commented Jun 2, 2021

@javiercn any ideas here?

@javiercn
Copy link
Member

javiercn commented Jun 2, 2021

@Pilchie It's a combo between the custom environment and Docker.

The way docker works from VS requires the environment to be Development. Otherwise we don't try to probe the filesystem for the developer certificate (for security reasons).

When you use a custom environment you need to setup the certificate explicitly via config.

We have docs here and here on how to do this setup.

@javiercn javiercn transferred this issue from dotnet/core Jun 2, 2021
@javiercn javiercn added area-commandlinetools Includes: Command line tools, dotnet-dev-certs, dotnet-user-jwts, and OpenAPI docker feature-devcerts ✔️ Resolution: Answered Resolved because the question asked by the original author has been answered. question labels Jun 2, 2021
@ghost ghost added the Status: Resolved label Jun 2, 2021
@Tratcher
Copy link
Member

Tratcher commented Jun 2, 2021

@javiercn where's the logic that checks for Development in this situation?

@Kla3mus
Copy link
Author

Kla3mus commented Jun 3, 2021

I did some experimenting and since you're switching the environment to one that is not from the predefined 3: Development, Staging, Production; it's somehow not able to pick up the trusted cert. I assume there's some piece of configuration that needs to be done for the new environment.

Is using your custom environment something that's necessary for you? I assume that if you switch back to "Development" it will work.

@Pilchie My knowledge here is lacking. Is this something unsupported? Or is there anything the customer can do to make it work?

This is indeed needed. I have an application with setups for multiple clients, which requires multiple configurations. It loads various modules for various clients, and various connectionstrings for these various clients.

@Kla3mus
Copy link
Author

Kla3mus commented Jun 3, 2021

@Pilchie It's a combo between the custom environment and Docker.

The way docker works from VS requires the environment to be Development. Otherwise we don't try to probe the filesystem for the developer certificate (for security reasons).

When you use a custom environment you need to setup the certificate explicitly via config.

We have docs here and here on how to do this setup.

Thanks! I'll take a look at the documentation. Does this mean that this lack of feature is intentional, and that it won't be implemented?

Edit:

I have tried and failed a bit with the documentation.
Both articles says to do these things:

dotnet dev-certs https -ep %USERPROFILE%\.aspnet\https\aspnetapp.pfx -p { password here }
dotnet dev-certs https --trust

Which I have already done, in Visual Studio's Developer Powershell view, and shown in the question. It just says; "A valid HTTPS certificate is already present." - further, trusting it works just fine, since it already has a valid one. And there's no change to the behavior. In addition, I have tried switching $env:USERPROFILE to $env:Test just to see if this could have any impact. (It didn't)

Have I possibly misunderstood something here?

Further, in both articles, they try to reference this certificate on my local machine, but if I have to create these by myself locally on my machine, won't this have to be re-done whenever someone else gets the solution to their computer?

Edit 2:
I tried doing the same without docker (which I would be very sad to do) but found other strange behaviors.
I added the following in launchSettings.json:

    "IIS Express - Test": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Test"
      }
    },

Selected the profile and ran the application. In this case it's missing a CSS file.
image

It leaves me wondering if this is not the preferred way to switch an application's behavior based on a computer/server setup. Should I aim for a different approach?

We have a modular application which is set up on a per customer basis. There are different DB layers and different logic-modules per customer. In addition to this we need to be able to set up staging per these. Until now I have wanted to use profiles for all of this. Set Environment variable to "customer-staging" or "customer-production" and the application would load the modules with dependency injection and connectionstrings from appsettings based on the environment variable.

To me, these kind of profiles seems to be the perfect solution, but I'm starting to understand that this might not be the way?

@ghost
Copy link

ghost commented Jun 4, 2021

This issue has been resolved and has not had any activity for 1 day. It will be closed for housekeeping purposes.

See our Issue Management Policies for more information.

@ghost ghost closed this as completed Jun 4, 2021
@javiercn
Copy link
Member

javiercn commented Jun 4, 2021

@Kla3mus If you have that type of advanced setup, we recommend you explicitly use your own certificate with it instead of relying on dev-certs.

Kestrel will only load the development certificate when it finds it on the certificate store (which indicates the SDK is installed on the machine) or when the app is running under Development and we find the certificate file with a specific naming convention in the right folder as well as the associated password for the cert in the config.

Docker tooling across IDEs (VS, VS 4 Mac, VS Code) will export the certificate into a path that they then map on the docker container being run, which is why this works when running from an IDE without you having to do anything.

The recommendation if you have a custom environment is that you setup the Default https certificate in your docker-compose.overrides.yml or similar.

  • Export the cert to a folder.
  • Map the folder as a volume on the container.
  • Setup the password in user secrets under Kestrel -> Certificates -> Default.
  • Setup the path to the certificate on appSettings.myEnvironment.json

@Kla3mus
Copy link
Author

Kla3mus commented Jun 10, 2021

Hmm...

If I had three environments. Development, Staging and Production. Would that also be considered "advanced setup"? Is it so that the only valid profile that is supposed to work with docker is the Development profile? And everything else is considered "advanced" ? I find this very strange. Why even have profiles if this is the case?

As for suggestion, I will repeat a question that has gone unanswered earlier; "Further, in both articles, they try to reference this certificate on my local machine, but if I have to create these by myself locally on my machine, won't this have to be re-done whenever someone else gets the solution to their computer?"

The suggestion you have, will that work across development machines and setups? The way I understand it is that all the developers have to export a certificate to a folder, map it to the container, then update the user-secrets...

Is this correct?

@javiercn

@ghost ghost locked as resolved and limited conversation to collaborators Jul 14, 2021
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-commandlinetools Includes: Command line tools, dotnet-dev-certs, dotnet-user-jwts, and OpenAPI docker feature-devcerts ✔️ Resolution: Answered Resolved because the question asked by the original author has been answered. question Status: Resolved
Projects
None yet
Development

No branches or pull requests

5 participants