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

Implement SSLContext factory #1815

Closed
wants to merge 20 commits into from
Closed

Conversation

aswanidutt87
Copy link

No description provided.

@aswanidutt87 aswanidutt87 mentioned this pull request Dec 21, 2022
2 tasks
@@ -446,6 +448,9 @@ def load(self) -> None:
ca_certs=self.ssl_ca_certs,
ciphers=self.ssl_ciphers,
)

elif self.ssl_context:
self.ssl = self.ssl_context.custom_ssl_context_factory() # type: ignore
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
self.ssl = self.ssl_context.custom_ssl_context_factory() # type: ignore
self.ssl = self.ssl_context()

this should do it no ? I dont get it otherwise

Copy link
Author

Choose a reason for hiding this comment

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

it wont work with out calling the callable, here is my usage

class SSL_Context(object):
    @classmethod
    def __call__(self):
        context = ssl.SSLContext(int(ssl.PROTOCOL_TLS))
        context.load_cert_chain(certfile=tls_cert, keyfile=tls_key)
        if allowed_ciphers:
            context.set_ciphers(allowed_ciphers)
        if list_options:
            for each_option in list_options:
                context.options |= each_option
        return context

ssl_context = SSL_Context

    uvicorn.run(
        "web:app",
        host="0.0.0.0",
        port=int(port),
        reload=True,
        ssl_context=ssl_context,
    )

and inside config.py

        elif self.ssl_context:
            self.ssl = self.ssl_context.__call__()  # type: ignore

@Kludex
Copy link
Member

Kludex commented Dec 25, 2022

The way I see this feature is something like:

from ssl import SSLContext

import uvicorn

def ssl_context_factory(context: SSLContext) -> SSLContext:
    return context

if __name__ == "__main__":
    uvicorn.run("main:app", ssl_context_factory=ssl_context_factory)

All the SSL parameters we have can be used together with the ssl_context_factory parameter.

If using this feature via python code, then the above is what I imagine. If we also want to use it via CLI, I guess we'd need to use the import_string that we have - but the CLI can wait for the python code part to be ready.

@Kludex Kludex added tls/ssl waiting author Waiting for author's reply labels Dec 25, 2022
@aswanidutt87
Copy link
Author

The way I see this feature is something like:

from ssl import SSLContext

import uvicorn

def ssl_context_factory(context: SSLContext) -> SSLContext:
    return context

if __name__ == "__main__":
    uvicorn.run("main:app", ssl_context_factory=ssl_context_factory)

All the SSL parameters we have can be used together with the ssl_context_factory parameter.

If using this feature via python code, then the above is what I imagine. If we also want to use it via CLI, I guess we'd need to use the import_string that we have - but the CLI can wait for the python code part to be ready.

got it updated with your suggestions as follows.

def ssl_context() -> ssl.SSLContext:
    context = ssl.SSLContext(int(ssl.PROTOCOL_TLS))
    context.load_cert_chain(certfile=tls_cert, keyfile=tls_key)
    if allowed_ciphers:
        context.set_ciphers(allowed_ciphers)
    if list_options:
        for each_option in list_options:
            context.options |= each_option
    return context

    uvicorn.run(
        "web:app",
        host="0.0.0.0",
        port=int(port),
        reload=True,
        ssl_context_factory=ssl_context,
    )

in config.py
        elif self.ssl_context_factory:
            self.ssl = self.ssl_context_factory()

@aswanidutt87 aswanidutt87 requested a review from euri10 December 27, 2022 15:40
@aswanidutt87
Copy link
Author

@Kludex / @euri10 please review, I have modified per your suggestions, i think this should work

uvicorn/main.py Outdated
@@ -319,6 +319,13 @@ def print_version(ctx: click.Context, param: click.Parameter, value: bool) -> No
help="Ciphers to use (see stdlib ssl module's)",
show_default=True,
)
@click.option(
"--ssl-context-factory",
type=typing.Callable,
Copy link
Member

Choose a reason for hiding this comment

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

This can't be a callable. What I said was to load the function object from the path... Which I'm not sure if we really should make this available via CLI.

Copy link
Member

Choose a reason for hiding this comment

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

There are messages I've written here that you ignored. I'm not reviewing this again without them addressed.

The code changes here don't fully take in consideration my previous comments.

@@ -446,6 +448,9 @@ def load(self) -> None:
ca_certs=self.ssl_ca_certs,
ciphers=self.ssl_ciphers,
)

elif self.ssl_context_factory:
self.ssl = self.ssl_context_factory()
Copy link
Member

Choose a reason for hiding this comment

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

Hmm... Maybe we shouldn't ignore the previous parameters passed? 🤔

What I propose was for the factory function to receive a SSLContext, which would be the one that uvicorn creates on the lines above.

@Kludex
Copy link
Member

Kludex commented Feb 16, 2023

@aswanidutt87 Are you still interested on this?

@aswanidutt87
Copy link
Author

@aswanidutt87 Are you still interested on this?

yes @Kludex , we really need this,
regarding your question "Hmm... Maybe we shouldn't ignore the previous parameters passed? " its either we pass the parameters to build the ssl_context in the uvicorn code or pass the custom created ssl_context directly to uvicorn, it cant be both at the same time.
and for the second question "What I propose was for the factory function to receive a SSLContext, which would be the one that uvicorn creates on the lines above. ", thats the whole problem that we cant pass the SSLContext or any other object for that matter, so passing a ssl_context_factory and return SSLContext wherever we need it.
please advise

@aswanidutt87
Copy link
Author

aswanidutt87 commented Feb 16, 2023

@Kludex - also, for our case or in general adding ssl_options will suffice all the use cases as the uvicorn code already have all the options except the ssl_options, so kindly consider this pr also-#1692

@Kludex
Copy link
Member

Kludex commented Feb 17, 2023

ontext wherever we need it.

The factory is meant to be called only when the SSLContext is needed, not in the Config, that's why it's the same problem as before... That's not the idea. I've pasted a link on how it's intended to be done on Gunicorn, and here would be analogous.

@aswanidutt87
Copy link
Author

aswanidutt87 commented Feb 17, 2023

@Kludex

I have modified the code to incorporate your suggestion of consuming the passed parameters to the custom ssl_context supplied.
please review

@Kludex
Copy link
Member

Kludex commented Mar 9, 2023

Would you mind fixing the linter, and removing the parameter from the CLI parameters?

@Kludex Kludex changed the title Issue #806 Implement SSLContext factory Mar 9, 2023
@aswanidutt87
Copy link
Author

Would you mind fixing the linter, and removing the parameter from the CLI parameters?

@Kludex , Linter is happy when I ran in my local
image

Reg: the removal of parameter from the CLI, then the test_cli is breaking.
image

@Kludex
Copy link
Member

Kludex commented Mar 12, 2023

@aswanidutt87 You probably need to update your dependencies. Please also run ./scripts/lint.

@aswanidutt87
Copy link
Author

aswanidutt87 commented Mar 13, 2023

@aswanidutt87 You probably need to update your dependencies. Please also run ./scripts/lint.
@Kludex lint is clean I guess

image

and regarding the test_cli fail, since we removed the @click.option(
"--ssl-context", from main.py but still it has ssl_context: typing.Callable, as one of the parameter, the test_cli is failing with below error . not sure what dependencies I need to update so that the test_cli is happy.
image

@aswanidutt87
Copy link
Author

@aswanidutt87 You probably need to update your dependencies. Please also run ./scripts/lint.
@Kludex lint is clean I guess

image

and regarding the test_cli fail, since we removed the @click.option( "--ssl-context", from main.py but still it has ssl_context: typing.Callable, as one of the parameter, the test_cli is failing with below error . not sure what dependencies I need to update so that the test_cli is happy. image

@Kludex , please let me know if we really need to remove the entry for CLI parameter, and if so how to fix the test failure due to the removal of CLI parameter.

@aswanidutt87
Copy link
Author

aswanidutt87 commented May 25, 2023

@Kludex / @euri10 please review the comment above and suggest

@aswanidutt87
Copy link
Author

@Kludex / @euri10 please review the comment above and suggest

hello @Kludex / @euri10 , could you please review this change and approve/comment. we need this custom ssl_context for our use case.

@Kludex
Copy link
Member

Kludex commented Jul 4, 2023

I've commented already: #1815 (comment)

@aswanidutt87
Copy link
Author

I've commented already: #1815 (comment)

@Kludex the latest comment is #1815 (comment) , if I remove the CLI parameter for --ssl-context, the test_cli is failing, I need help here.

uvicorn/main.py Outdated
@@ -319,6 +319,13 @@ def print_version(ctx: click.Context, param: click.Parameter, value: bool) -> No
help="Ciphers to use (see stdlib ssl module's)",
show_default=True,
)
@click.option(
"--ssl-context-factory",
type=typing.Callable,
Copy link
Member

Choose a reason for hiding this comment

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

There are messages I've written here that you ignored. I'm not reviewing this again without them addressed.

The code changes here don't fully take in consideration my previous comments.

@Kludex
Copy link
Member

Kludex commented Feb 19, 2024

Also, the pipeline is not passing... ???

@UnshiftedEarth

This comment was marked as spam.

MadsRC added a commit to MadsRC/uvicorn that referenced this pull request Apr 5, 2024
@MadsRC MadsRC mentioned this pull request Apr 5, 2024
3 tasks
MadsRC added a commit to MadsRC/uvicorn that referenced this pull request Apr 5, 2024
@Kludex
Copy link
Member

Kludex commented Apr 13, 2024

Closing as stale.

@Kludex Kludex closed this Apr 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
tls/ssl waiting author Waiting for author's reply
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants