HTTPie ignora certificados do sistema
http --debug -j https://example_using_my_ca.com
HTTPie 0.9.3
HTTPie data: /home/lukas/.httpie
Requests 2.10.0
Pygments 1.6
Python 3.4.3 (default, Oct 14 2015, 20:28:29)
[GCC 4.8.4] linux
>>> requests.request(**{'allow_redirects': False,
'auth': None,
'cert': None,
'data': '',
'files': DataDict(),
'headers': {'Accept': b'application/json',
'Content-Type': b'application/json',
'User-Agent': b'HTTPie/0.9.3'},
'method': 'get',
'params': ParamsDict(),
'proxies': {},
'stream': True,
'timeout': 30,
'url': 'https://example_using_my_ca.com',
'verify': True})
Traceback (most recent call last):
File "/usr/local/lib/python3.4/dist-packages/requests/packages/urllib3/connectionpool.py", line 578, in urlopen
chunked=chunked)
File "/usr/local/lib/python3.4/dist-packages/requests/packages/urllib3/connectionpool.py", line 351, in _make_request
self._validate_conn(conn)
File "/usr/local/lib/python3.4/dist-packages/requests/packages/urllib3/connectionpool.py", line 814, in _validate_conn
conn.connect()
File "/usr/local/lib/python3.4/dist-packages/requests/packages/urllib3/connection.py", line 289, in connect
ssl_version=resolved_ssl_version)
File "/usr/local/lib/python3.4/dist-packages/requests/packages/urllib3/util/ssl_.py", line 308, in ssl_wrap_socket
return context.wrap_socket(sock, server_hostname=server_hostname)
File "/usr/lib/python3.4/ssl.py", line 365, in wrap_socket
_context=self)
File "/usr/lib/python3.4/ssl.py", line 601, in __init__
self.do_handshake()
File "/usr/lib/python3.4/ssl.py", line 828, in do_handshake
self._sslobj.do_handshake()
ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:600)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/local/lib/python3.4/dist-packages/requests/adapters.py", line 403, in send
timeout=timeout
File "/usr/local/lib/python3.4/dist-packages/requests/packages/urllib3/connectionpool.py", line 604, in urlopen
raise SSLError(e)
requests.packages.urllib3.exceptions.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:600)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/local/bin/http", line 11, in <module>
sys.exit(main())
File "/usr/local/lib/python3.4/dist-packages/httpie/core.py", line 115, in main
response = get_response(args, config_dir=env.config.directory)
File "/usr/local/lib/python3.4/dist-packages/httpie/client.py", line 48, in get_response
response = requests_session.request(**kwargs)
File "/usr/local/lib/python3.4/dist-packages/requests/sessions.py", line 475, in request
resp = self.send(prep, **send_kwargs)
File "/usr/local/lib/python3.4/dist-packages/requests/sessions.py", line 585, in send
r = adapter.send(request, **kwargs)
File "/usr/local/lib/python3.4/dist-packages/requests/adapters.py", line 477, in send
raise SSLError(e, request=request)
requests.exceptions.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:600)
Para referência, curl funciona bem: curl https://example_using_my_ca.com
Faria sentido usar ssl.get_default_verify_paths () para obter os caminhos padrão?
Eu proporia o seguinte comportamento:
Se --verify for passado um parâmetro diferente de não ou sim, passe o parâmetro para as solicitações.
Se --verify estiver definido como sim:
1) se REQUESTS_CA_BUNDLE estiver definido, passe True para verificar as solicitações.
2) a variável de ambiente elif ssl.get_default_verify_paths (). Openssl_cafile_env está definida, passe para a verificação de solicitações
4) a variável de ambiente elif ssl.get_default_verify_paths (). Openssl_capath_env é definida para passar para verificar as solicitações
5) elif ssl.get_default_verify_paths (). Capath não é Nenhum, passe para as solicitações de verificação
6) caso contrário, passe True para verificar as solicitações
mas observe que ssl.get_default_verify_paths está disponível apenas a partir de python3.4
@luv não só está disponível nas versões 3.4+ e 2.7.10+, mas também não funciona em todas as plataformas. É por isso que o Request está trabalhando em seu próprio problema para resolver isso para as pessoas. Por favor, pare de comentar constantemente sobre httpie. Essa é uma preocupação que existe em solicitações e não em httpie IMO.
@ sigmavirus24 wtf man? Não tenho ideia do que você quer dizer com comentar constantemente, mas enfim, vejo que você nem mesmo é um colaborador httpie. Presumo que seja apenas um troll estúpido: /
uma rápida olhada no código-fonte curl para ver como é uma implementação funcional ....
Desconsiderando todos os ifdefs amiga e VMS e o suporte para muitas bibliotecas ssl diferentes, é realmente muito estúpido e não está usando métodos de pesquisa do openssl X509_ * (como, por exemplo, usado em get_default_verify_paths () no módulo SSL do Python).
Em vez disso, curl simplesmente itera sobre um monte de locais conhecidos no momento da compilação (veja este m4dness https://github.com/curl/curl/blob/master/acinclude.m4#L2560) e então suporta explicitamente a substituição com (CURL_CA_BUNDLE e ) Variáveis de ambiente SSL_CERT_DIR e SSL_CERT_FILE em tempo de execução (novamente não usando coisas como X509_get_default_cert_file_env ()). É isso aí.
Então, que tal implementar a mesma abordagem em Python puro? (Sim, parece rápido e sujo, mas funciona para curl!), Mas adicionando suporte para Windows (ssl.enum_certificates?) E OS X (não tenho certeza aqui, mas o python parece usar a biblioteca openssl fornecida pela apple no OS X 10.6+ então isso já deve estar bom!).
@luv obrigado pelo relatório, mas por favor seja mais respeitoso com os outros membros. @ sigmavirus24 é um desenvolvedor central de solicitações nas quais httpie se baseia para todo o HTTP e sem as quais ele nem existiria, então sua visão é extremamente relevante.
observe que isso não será corrigido nas solicitações até o lançamento 3.0.0 ... nem mesmo SSL_CERT_FILE terá suporte devido a possíveis problemas de compatibilidade https://github.com/kennethreitz/requests/pull/2903
btw. Eu não queria ser desrespeitoso, eu realmente pensei que ele / ela estava trollando :) Saí do meu caminho para ajudar a encontrar uma solução para um problema e alguém que nem uma vez contribuiu para o projeto (verifiquei os contribuidores de HTTPie porque fiquei realmente surpreso com a reação hostil) estava basicamente me dizendo para calar a boca: /
@luv, eu não estava dizendo para você calar a boca. Há 763 pessoas inscritas nesta edição. 100% deles _podem_ receber e-mails por isso (mas provavelmente é mais como 70% ou ~ 534). Isso significa que você gerou (nas 2 horas após a abertura do problema) cerca de 1602 e-mails (possivelmente mais ou menos). Em outras palavras, você está enviando spam para as pessoas com um fluxo de postagens conscientes como essa. A melhor maneira de documentar novas informações quando ninguém lhe respondeu é editando a postagem original.
Finalmente, as contribuições de código não são a única contribuição para um projeto. Se você quiser ver todas as contribuições em um projeto, você pode usar um projeto como o octohatrack . Respondi a várias solicitações relacionadas a bugs no httpie para @jkbrzt porque eles não têm tempo para acompanhar o desenvolvimento das solicitações. Quando vejo um bug relacionado a solicitações aqui, eu respondo porque 99% das vezes, ele já está sendo tratado. Felizmente para @jkbrzt , já fui tratado como mal (e algumas vezes pior) antes, então tenho a pele mais grossa.
Como uma observação lateral, "eles" tem tantos caracteres quanto "ele / ela" e é aplicável de forma muito mais geral, pois pode ser usado para se referir a uma única pessoa também.
então estamos consertando isso?
@jkbrzt Eu chamaria isso de recurso, não de bug. É intencional que Requests funcione de forma idêntica em Windows, * nixes e BSDs e, de fato, muitas distribuições de sistema de Requests ativamente removem esse comportamento e apontam para o armazenamento / pacote de certificados do sistema. Portanto, se os usuários precisarem desse comportamento, eles podem usar a versão de Requests empacotada por seus distribuidores de sistema com HTTPie (e possivelmente o sistema HTTPie empacotado).
Quanto a "consertar isso", depende da sua definição de consertado. Este é um recurso que _será_ adicionado às Solicitações. Nesse ponto, o HTTPie obterá o comportamento gratuitamente. Se, em vez disso, o HTTPie considerar isso uma prioridade mais alta (o que @jkbrzt pode fazer como achar melhor), eles podem duplicar o esforço de desenvolvimento para criar uma versão que faça isso antes.
Como parece que você está usando o linux, @luv , você pode tirar vantagem do fato de que sua distribuição do linux quase certamente tem uma versão do Requests que usa o armazenamento de certificados do sistema hoje. Requests são empacotados em todas as distribuições do Linux que verifiquei e praticamente todas essas distribuições usam seu armazenamento de certificados do sistema. Se este não for o caso, talvez você deva registrar um bug com o mantenedor do pacote Requests dessa distribuição.
mesmo problema com HTTPie instalado via apt (ubuntu 14.04lts)
@luv, isso é surpreendente porque eu sei com
Limpei todos os "pedidos" e versões "httpie" para verificar se a distribuição ubuntu do httpie é usada e você está certo, eu ainda estava usando o httpie do PyPI. Ubuntu httpie falha com "ImportError: não é possível importar o nome is_windows" que é um problema conhecido.
Acho que esqueci de executar "pip3 uninstall" e executei apenas "pip uninstall", pois antes de mais nada tive que usar o python3 para fazer o SSL funcionar.
Peço desculpas a 761 pessoas por "spam" com a descrição da minha configuração httpie.
Estou usando Gentoo Linux, httpie-0.9.9 e requests-2.18.4 (mais recente disponível no Gentoo) instalados em todo o sistema pelo gerenciador de pacotes, nenhuma outra versão instalada (nem tenho o pip instalado). Outras ferramentas (openssl s_client, sslclient, curl) detectam o certificado CA local instalado e funcionam bem, mas httpie falha:
$ openssl s_client -quiet -connect localhost:8082
depth=1 CN = Local CA home.lan
verify return:1
depth=0 CN = localhost
verify return:1
^C
$ http -v https://localhost:8082/
http: error: SSLError: HTTPSConnectionPool(host='localhost', port=8082): Max retries exceeded with url: / (Caused by SSLError(SSLError("bad handshake: Error([('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')],)",),)) while doing GET request to URL: https://localhost:8082/
Devo atualizar algo para que funcione?
@powerman Essa é uma questão mais apropriada para os redistribuidores gentoo desses pacotes.
@ sigmavirus24 Por que isso? Minha pergunta é que essas solicitações / versões httpie devem lidar com a lista de CA do sistema ou não. Se sim, então provavelmente algo está configurado incorretamente em meu sistema ou há um bug. Se não, qual versão preciso para fazer funcionar.
@powerman nada mudou. Nenhum dos dois oferece suporte aos pacotes de certificado do sistema, mas se você instalou ambos a partir do gerenciador de pacotes de sua distribuição, é provável que tenham corrigido o software para usá-los. Se você usou os pacotes disponíveis no Gentoo e eles não estão usando certificados de sistema, então é um problema do Gentoo.
Só vou adicionar um comentário adicional sobre isso: Eu uso um proxy que é projetado especificamente para que quando você fizer solicitações SSL, ele estabeleça um túnel seguro entre você e o proxy e depois outro entre o proxy e o destino. Ele faz isso para que eu possa monitorar com segurança o tráfego que passa pelo meu proxy para garantir que ninguém esteja tentando fazer algo desagradável e ocultá-lo. Infelizmente, isso significa que o certificado que httpie recebe de volta não é confiável (porque está na raiz do sistema, mas httpie não o usa).
Na verdade, posso reproduzir o mesmo problema no NixOS.
4+ anos depois ...