Python Uvicorn - получить информацию о сертификате SSL - PullRequest
4 голосов
/ 06 мая 2020

У меня есть стек gunicorn + uvicorn + fastApi. (В основном я использую изображение https://hub.docker.com/r/tiangolo/uvicorn-gunicorn-fastapi docker).

Я уже реализовал аутентификацию на основе SSL, предоставив соответствующие параметры конфигурации Gunicorn: certfile, keyfile, ca_certs, cert_reqs. И он работает нормально: пользователь должен предоставить клиентский сертификат SSL, чтобы иметь возможность выполнять вызовы API.

Что мне нужно сделать сейчас, так это получить данные сертификата клиента и передать их дальше (добавить их в заголовки запросов) в мое приложение, поскольку оно содержит некоторые учетные данные клиента. Например, я нашел способ сделать это с помощью воркера-пулеметчика, заменив gunicorn.workers.sync.SyncWorker: https://gist.github.com/jmvrbanac/089540b255d6b40ca555c8e7ee484c13.

Но есть ли способ сделать то же самое, используя UvicornWorker? Я попытался просмотреть исходный код UvicornWorker, но не нашел способа сделать это.

Я углубился в исходный код Uvicorn и, насколько я понимаю, в чтобы получить доступ к данным сертификата TLS клиента, мне нужно проделать некоторые трюки с python библиотекой asyncio (https://docs.python.org/3/library/asyncio-eventloop.html), возможно, с классом Server (https://docs.python.org/3/library/asyncio-eventloop.html#asyncio .Server ) и переопределить некоторые методы UvicornWorker. Я все еще не совсем уверен, можно ли добиться желаемого результата.

1 Ответ

1 голос
/ 11 мая 2020

В итоге я установил nginx (Openresty) перед своим сервером и добавил скрипт для получения сертификата клиента и помещения его в заголовок.

Вот часть моей nginx конфигурации :

set_by_lua_block $client_cert {
    local client_certificate = ngx.var.ssl_client_raw_cert
    if (client_certificate ~= nil) then
        client_certificate = string.gsub(client_certificate, "\n", "")
        ngx.req.set_header("X-CLIENT-ID", client_certificate)
    end
    return client_certificate
}

Также возможно извлечь некоторые специфические поля c из сертификата клиента (например, CN, серийный номер и т. Д. c.) Непосредственно внутри конфигурации nginx, но я решил пропустить весь сертификат далее.

Моя проблема решена без использования пулемета, как я изначально хотел, но это единственное хорошее решение, которое я нашел.

...