Skip to content

Introduce KestrelServerOptions.CheckDefaultCertificate #48057

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

Closed
wants to merge 4 commits into from

Conversation

amcasey
Copy link
Member

@amcasey amcasey commented May 4, 2023

Introduce KestrelServerOptions.HasDefaultOrDevelopmentCertificate

  • You've read the Contributor Guide and Code of Conduct.
  • You've included unit or integration tests for your change, where applicable.
  • You've included inline docs for your change, where applicable.
  • There's an open issue for the PR that you are making. If you'd like to propose a new feature or change, please open an issue to discuss the change or find an existing issue.

Description

Introduce KestrelServerOptions.HasDefaultOrDevelopmentCertificate as a way to determine whether a certificate is available before invoking KestrelServerOptions.Listen and possibly failing in ListenOptions.UseHttps.

Replaces #48054
Fixes #28120

...as a way to determine whether a certificate is available before invoking `KestrelServerOptions.Listen` and possibly failing in `ListenOptions.UseHttps`.

Fixes dotnet#28120
@ghost ghost added the area-runtime label May 4, 2023
@amcasey amcasey added blocked The work on this issue is blocked due to some dependency and removed area-runtime labels May 4, 2023
@amcasey
Copy link
Member Author

amcasey commented May 4, 2023

Blocked on API approval: #48055

/// </summary>
/// <returns>True if there is a default or development server certificate, false otherwise.</returns>
/// <exception cref="InvalidOperationException">If there is a configuration and it has not been loaded.</exception>
public bool HasDefaultOrDevelopmentCertificate
Copy link
Member

Choose a reason for hiding this comment

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

Not super enthusiastic about a property getter having side effects.

Copy link
Member

@Tratcher Tratcher May 4, 2023

Choose a reason for hiding this comment

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

Yeah, make it a method.

bool CheckForDefaultCertificate()

The development certificate counts as a default and is explained in the docs.

Copy link
Member Author

Choose a reason for hiding this comment

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

What side-effect are we worried about? Enabling https config?

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not familiar with the bool CheckFoo() naming convention - personally, I'd expect that method to throw if the condition weren't satisfied. I take it we use that elsewhere?

Copy link
Member Author

Choose a reason for hiding this comment

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

Renamed and made it a method, but I'd still like to understand more about side-effects.

Copy link
Member Author

Choose a reason for hiding this comment

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

Incidentally, now that it doesn't actually return the cert, I would be fine with this throwing if https configuration isn't enabled.

Copy link
Member Author

Choose a reason for hiding this comment

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

The point of the method is to avoid throwing for known, common conditions. Exceptions should only be used for unexpected conditions.

Sorry, I'm not sure which part of the thread you're responding to. If it was about my expectation that CheckFoo would throw, that was an intuition about the naming convention and not a comment on how this member (whatever name and shape it ends up taking) should behave.

Copy link
Member

Choose a reason for hiding this comment

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

This is a friendly guard method, letting you check the state in a controlled way to avoid an exception later. It should not throw an exception.

Copy link
Member Author

Choose a reason for hiding this comment

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

@halter73 Asked me to have it throw in that case. Would you like me to work up a version that loads eagerly and then compensates if the configuration changes?

Copy link
Member

Choose a reason for hiding this comment

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

If you're getting conflicting advice we should hold off until we can discuss it in a meeting, API review or otherwise.

/// <exception cref="InvalidOperationException">If there is a configuration and it has not been loaded.</exception>
public bool CheckDefaultCertificate()
{
if (ConfigurationLoader is { IsLoaded: false })
Copy link
Member

Choose a reason for hiding this comment

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

Can this call ConfigurationLoader.Load() instead of throwing?

Copy link
Member Author

Choose a reason for hiding this comment

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

@halter73 Suggested doing it this way because invoking Load ourselves would put the burden on us to reload on change.

Copy link
Member

Choose a reason for hiding this comment

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

We'd have to reload if CheckDefaultCertificate were called again? That seems reasonable.

Copy link
Member Author

Choose a reason for hiding this comment

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

I understood him to say that config changes between the first call to Load and bind-time would be lost since bind wouldn't attempt to reload and already loaded configuration.

Copy link
Member Author

Choose a reason for hiding this comment

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

(i.e. other consumers of the configuration might see stale values.)

Copy link
Member

Choose a reason for hiding this comment

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

@halter73 Suggested doing it this way because invoking Load ourselves would put the burden on us to reload on change.

We should capture the reload token during the first call to Load regardless. If we start calling Load ourselves in more places, we should fix the bug at the same time. Otherwise, we risk not picking up new endpoints or certa added to Kestrel config between the manual call to Load and a later call to StartAsync. We could always call Reload during StarAsync, but it'd be more efficient to only reload if the configuration has actually changed.

That said, this is a pretty narrow edge case and an existing big.

/// </summary>
/// <returns>True if there is a default or development server certificate, false otherwise.</returns>
/// <exception cref="InvalidOperationException">If there is a configuration and it has not been loaded.</exception>
public bool HasDefaultOrDevelopmentCertificate
Copy link
Member

Choose a reason for hiding this comment

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

This is a friendly guard method, letting you check the state in a controlled way to avoid an exception later. It should not throw an exception.

@amcasey amcasey changed the title Introduce KestrelServerOptions.HasDefaultOrDevelopmentCertificate Introduce KestrelServerOptions.CheckDefaultCertificate May 8, 2023
@amcasey
Copy link
Member Author

amcasey commented May 8, 2023

We're going to try to fix things without a new API.

@amcasey amcasey closed this May 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
blocked The work on this issue is blocked due to some dependency
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Preload default Kestrel config before running Kestrel's configureOptions callback
5 participants