问题描述
由于我的Kubernetes集群没有自己的FQDN,我遇到了一些Python和请求问题。
简而言之,它是一个群集,具有许多不同的名称空间和入口。内部路由是根据请求标头和列入白名单的IP中的主机来管理的。当我尝试将获取请求(带有客户端证书)拍摄到IP时,出现以下异常:HTTPSConnectionPool(host='*MyExternalIpAddr*',port=443): Max retries exceeded with url: /test(Caused by SSLError(SSLCertVerificationError(1,'[SSL: CERTIFICATE_VERIFY_Failed] certificate verify Failed: unable to get local issuer certificate (_ssl.c:1076)')))
我遇到的问题归因于以下代码:
url = "https://*MyExternalIpAddr*/test"
headers = {"Host":"*TheHostnameInTheCluster*"}
cert = (cert_file_path,key_file_path)
r = requests.get(url,headers=headers,cert=cert,auth=auth,verify=ca_file)
我99%的确定IR-url是问题所在,因为如果我将外部IP映射到drivers / etc / host中的主机名(并将URL更改为“ https:// hostname / test”),请求顺利通过。
现在,我假设它与Requests根据rootCA(CN或SAN?)检查客户端证书的方式有关。不幸的是,我还不够聪明,无法用Google搜索过去的经历。
值得一提的是,所有证书都是使用openSSL自行生成的,因此我可以根据需要更改它们。尽管我也许可以将IP放在SAN中,但是由于集群中会有许多具有不同证书包的微服务,所以我认为这可能会导致冲突。(p)。
我希望找到一种聪明的方法来用Python解决这个问题,因此,我向您求助,这是互联网的巨大集体智慧。
期待您的回音(很抱歉,如果我忽略了先前对类似问题的回答;我已经四处搜寻,但无济于事)!
编辑
因此,我逐渐意识到问题与客户端证书无关,而与根CA验证服务器证书的方式有关。
我尝试将IP添加到服务器证书中的SAN中,并且可以正常工作。我的意思是说,当我从IP中“获取”(不得不使用主机文件中的FQDM映射的名称)时,邮递员再也不会摆出乱七八糟的样子了,但是不幸的是,请求没有跟上。有什么想法吗? :)
解决方法
所以我用ForcedIPHTTPSAdapter解决了它。
import requests
from requests.auth import HTTPBasicAuth
from forcediphttpsadapter.adapters import ForcedIPHTTPSAdapter
### You'll have to "pip install requests[security] forcediphttpsadapter" ###
if __name__ == "__main__":
cert_file_path = r"*path_to*\client.crt"
key_file_path = r"*path_to*\client.key"
ca_file = r"*path_to*\rootCA.crt"
auth = HTTPBasicAuth("*UID*","*PWD*")
### Cluster IP ###
cip = "*127.0.0.1*"
base_url = "*https://hostname.com*"
endpoint = "/test"
cert = (cert_file_path,key_file_path)
s = requests.Session()
s.mount(base_url,ForcedIPHTTPSAdapter(dest_ip=cip))
r = s.get(base_url + endpoint,cert=cert,auth=auth,verify=ca_file)
if r.status_code == 200:
print(r.text)
它的另一个好处是不必在标题中指定主机!