çŸä»£ã®ã€ã³ã¿ãŒãããéä¿¡ã«ãããŠãã»ãã¥ãªãã£ã¯éåžžã«éèŠã§ããç¹ã«ããŠã§ããµã€ããAPIãšã®éä¿¡ã§åºã䜿ãããŠããHTTPSã¯ãéä¿¡å
容ãæå·åããéä¿¡çžæãæ¬ç©ã§ããããšãä¿èšŒããããã«SSL/TLS蚌ææžãå©çšããŸããPythonã§HTTPSéä¿¡ãè¡ãéããã®èšŒææžã®æ€èšŒãé©åã«è¡ãããã«æ¬ ãããªãã©ã€ãã©ãªã certifi
ã§ãã
ãã®èšäºã§ã¯ãcertifi
ããªãå¿
èŠãªã®ããã©ã®ããã«æ©èœããã®ãããããŠå
·äœçãªäœ¿ãæ¹ã«ã€ããŠè©³ãã解説ããŠãããŸããPythonã䜿ã£ãéçºãè¡ãäžã§ãå®å
šãªéä¿¡ãå®çŸããããã®ç¥èãæ·±ããŠãããŸãããïŒ ð
`certifi` ãšã¯äœãïŒ ð€
certifi
ã¯ãä¿¡é Œã§ããèªèšŒå±ïŒCA: Certificate AuthorityïŒã®ã«ãŒã蚌ææžã®ã³ã¬ã¯ã·ã§ã³ãæäŸããPythonããã±ãŒãžã§ãããããã®ã«ãŒã蚌ææžã¯ãSSL/TLSéä¿¡æã«ãµãŒããŒããæ瀺ããã蚌ææžãæ£åœãªãã®ãã©ãããæ€èšŒããããã«äœ¿çšãããŸãã
å
·äœçã«ã¯ãcertifi
㯠Mozilla ãæ
éã«ãã¥ã¬ãŒãïŒåéã»æŽçïŒããã«ãŒã蚌ææžã®ãªã¹ãïŒCAãã³ãã«ïŒãå«ãã§ããŸããMozillaã¯äž»èŠãªãŠã§ããã©ãŠã¶ã§ããFirefoxãæäŸããŠããããã®èšŒææžã¹ãã¢ã¯åºãä¿¡é ŒãããŠããŸããcertifi
ã¯ããã®ä¿¡é Œæ§ã®é«ã蚌ææžãªã¹ããPythonã¢ããªã±ãŒã·ã§ã³ããç°¡åã«å©çšã§ããããã«ããã±ãŒãžåãããã®ã§ãã
ããšããšã¯ã人æ°ã®ããHTTPã¯ã©ã€ã¢ã³ãã©ã€ãã©ãªã§ãã requests
ãããžã§ã¯ãã®äžéšã§ãããã蚌ææžç®¡çã®éèŠæ§ãšç¬ç«æ§ãé«ããããã«å¥ã®ã©ã€ãã©ãªãšããŠåãåºãããŸããã
ð¡ ãã€ã³ã
certifi
ã¯ä¿¡é Œãããã«ãŒã蚌ææžã®ã³ã¬ã¯ã·ã§ã³ãæäŸããPythonã©ã€ãã©ãªã- Mozillaã管çããä¿¡é Œæ§ã®é«ã蚌ææžãªã¹ãïŒCAãã³ãã«ïŒãå©çšã
- HTTPSéä¿¡ã«ããããµãŒããŒèšŒææžã®æ€èšŒã«äœ¿çšãããã
- ããšããšã¯
requests
ã©ã€ãã©ãªã®äžéšã ã£ãã
ãªã `certifi` ãå¿ èŠãªã®ãïŒ ð
ãOSã«ã蚌ææžã¹ãã¢ãããã®ã«ããªãããããPythonã©ã€ãã©ãªãå¿ èŠãªã®ïŒããšçåã«æããããããŸãããããã«ã¯ããã€ãã®çç±ããããŸãã
1. OSéã®å·®ç°ãšç§»æ€æ§
ç°ãªãOSïŒWindows, macOS, Linuxãã£ã¹ããªãã¥ãŒã·ã§ã³ïŒã¯ãããããç¬èªã®èšŒææžç®¡çã·ã¹ãã ãšèšŒææžã¹ãã¢ãæã£ãŠããŸãããããã®å Žæã圢åŒã¯OSããšã«ç°ãªããŸããPythonã¢ããªã±ãŒã·ã§ã³ãæ§ã ãªç°å¢ã§åäœããå¿ èŠãããå ŽåãOSåºæã®èšŒææžã¹ãã¢ã«äŸåãããšãç°å¢ããšã®å·®ç°ã«å¯Ÿå¿ããã³ãŒããå¿ èŠã«ãªããè€éããå¢ããŸãã
certifi
ã¯ãOSã«äŸåããªãäžè²«ããæ¹æ³ã§ä¿¡é Œã§ããã«ãŒã蚌ææžã®ã»ãããæäŸããŸããããã«ãããPythonã¢ããªã±ãŒã·ã§ã³ã¯ã©ã®ç°å¢ã§å®è¡ãããŠããåãä¿¡é Œåºç€ã«åºã¥ããŠSSL/TLS蚌ææžã®æ€èšŒãè¡ãããšãã§ããé«ã移æ€æ§ãå®çŸããŸãã
2. 蚌ææžãªã¹ãã®é®®åºŠãšæŽæ°ã®å®¹æã
ã€ã³ã¿ãŒãããäžã®ä¿¡é Œé¢ä¿ã¯åžžã«å€åããŠãããæ°ããèªèšŒå±ãç»å Žããããæ¢åã®èªèšŒå±ãä¿¡é Œã倱ã£ããã蚌ææžã®å±æ®åïŒã»ãã¥ãªãã£äžã®åé¡ïŒãçºçãããããŸãããã®ãããã«ãŒã蚌ææžã®ãªã¹ãã¯å®æçã«æŽæ°ããå¿ èŠããããŸãã
OSã®èšŒææžã¹ãã¢ã®æŽæ°ã¯ãOSã®ã¢ããããŒãã«äŸåããããšãå€ããå¿ ãããã¿ã€ã ãªãŒã«è¡ããããšã¯éããŸããããŸããã¢ããªã±ãŒã·ã§ã³éçºè ãOSã®èšŒææžã¹ãã¢ã®æŽæ°ãçŽæ¥ã³ã³ãããŒã«ããããšã¯å°é£ã§ãã
certifi
ã¯ç¬ç«ããPythonããã±ãŒãžã§ãããããpip
ã³ãã³ãã䜿ã£ãŠç°¡åã«ææ°çã«æŽæ°ã§ããŸããããã«ãããã¢ããªã±ãŒã·ã§ã³ã¯åžžã«ææ°ã®ä¿¡é Œã§ãã蚌ææžãªã¹ããå©çšããããšãå¯èœã§ããã»ãã¥ãªãã£ã®èŠ³ç¹ãããcertifi
ãé »ç¹ã«æŽæ°ããããšãæšå¥šãããŠããŸãã
3. `requests` ã©ã€ãã©ãªãšã®é£æº
Pythonã§HTTPéä¿¡ãè¡ãéã«æãåºã䜿ãããŠããã©ã€ãã©ãªã®äžã€ã requests
ã§ããrequests
ã¯ãããã©ã«ãã§SSL蚌ææžã®æ€èšŒãè¡ããŸããããã®éã« certifi
ãã€ã³ã¹ããŒã«ãããŠããã°ãcertifi
ãæäŸããCAãã³ãã«ãèªåçã«äœ¿çšããŸãã
以åã®ããŒãžã§ã³ã® requests
(ããŒãžã§ã³ 2.16 ããå) ã§ã¯ãcertifi
ãã€ã³ã¹ããŒã«ãããŠããªãå Žåãrequests
ã©ã€ãã©ãªèªäœã«ãã³ãã«ãããå€ã蚌ææžãªã¹ãã䜿çšããŠããŸãããããã¯ãrequests
ã®ããŒãžã§ã³ãæŽæ°ããªãéã蚌ææžãªã¹ããæŽæ°ããããã»ãã¥ãªãã£äžã®ãªã¹ã¯ããããŸãããcertifi
ã䜿ãããšã§ãrequests
ã®ããŒãžã§ã³ãšã¯ç¬ç«ããŠèšŒææžãªã¹ããææ°ã«ä¿ã€ããšãã§ããŸãã
â ïž æ³šæ
SSL蚌ææžã®æ€èšŒãç¡å¹ã«ããããšã¯ãäžéè æ»æïŒMan-in-the-Middle attackïŒã®ãªã¹ã¯ãé«ãããããæ¬çªç°å¢ã§ã¯çµ¶å¯Ÿã«é¿ããã¹ãã§ããéçºç°å¢ããã¹ãç°å¢ã§ãã£ãŠããå¯èœãªéãæ€èšŒãè¡ãããã«ããŸãããã
# requests ã§æ€èšŒãç¡å¹ã«ããäŸ (éæšå¥šïŒ)
import requests
response = requests.get('https://example.com', verify=False)
`certifi` ã®ä»çµã¿ âïž
certifi
ã®äžå¿ãšãªãã®ã¯ãcacert.pem
ãšããååã®ãã¡ã€ã«ã§ãããã®ãã¡ã€ã«ã«ã¯ãMozillaãä¿¡é Œããã«ãŒã蚌ææžãPEM (Privacy-Enhanced Mail) 圢åŒã§é£çµãããŠæ ŒçŽãããŠããŸãã
PEM圢åŒã¯ã蚌ææžãç§å¯éµãããã¹ã圢åŒã§è¡šçŸããããã®æšæºçãªãã©ãŒãããã®äžã€ã§ã-----BEGIN CERTIFICATE-----
ãš -----END CERTIFICATE-----
ã§å²ãŸããBase64ãšã³ã³ãŒããããããŒã¿ã§æ§æãããŸããcacert.pem
ã«ã¯ãè€æ°ã®èšŒææžããã®åœ¢åŒã§é£ãªã£ãŠå«ãŸããŠããŸãã
certifi
ããã±ãŒãžãã€ã³ã¹ããŒã«ãããšããã® cacert.pem
ãã¡ã€ã«ãPythonã®site-packages
ãã£ã¬ã¯ããªå
ã«é
眮ãããŸããcertifi
ã©ã€ãã©ãªã¯ããã®ãã¡ã€ã«ã®å Žæãç¹å®ããããã®ã·ã³ãã«ãªé¢æ°ãæäŸããŸãã
éèŠãªç¹ãšããŠãcertifi
ã¯æäŸãããCAãã³ãã«ã®å
容ãå€æŽïŒèšŒææžã®è¿œå ãåé€ïŒããæ©èœã¯ãµããŒãããŠããŸãããããã¯ãäžè²«æ§ãããã移æ€æ§ã®é«ãä¿¡é Œã®åºç€ãæäŸããããšãç®çãšããŠããããã§ããããã«ã¹ã¿ã 蚌ææžïŒèªå·±çœ²å蚌ææžãäŒæ¥å
ã®ãã©ã€ããŒãCAãªã©ïŒã䜿çšããå¿
èŠãããå Žåã¯ãcertifi
ã® cacert.pem
ãçŽæ¥ç·šéããã®ã§ã¯ãªããHTTPã¯ã©ã€ã¢ã³ãã©ã€ãã©ãªïŒrequests
ãªã©ïŒã®æ©èœã䜿ã£ãŠã«ã¹ã¿ã 蚌ææžãã¡ã€ã«ãæå®ããããç°å¢å€æ°ïŒREQUESTS_CA_BUNDLE
ã SSL_CERT_FILE
ïŒã䜿çšããå¿
èŠããããŸãã
ã€ã³ã¹ããŒã«ãšåºæ¬çãªäœ¿ãæ¹ ð ïž
ã€ã³ã¹ããŒã«
certifi
ã¯PyPIã§å
¬éãããŠãããpip
ã䜿ã£ãŠç°¡åã«ã€ã³ã¹ããŒã«ã§ããŸãã
pip install certifi
requests
ã©ã€ãã©ãªãã€ã³ã¹ããŒã«ãããšãéåžžã¯äŸåé¢ä¿ãšã㊠certifi
ãèªåçã«ã€ã³ã¹ããŒã«ãããŸãã
pip install requests
# requests ãäŸåããŠãã certifi ãäžç·ã«ã€ã³ã¹ããŒã«ããã
ãã§ã«ã€ã³ã¹ããŒã«ãããŠããã確èªããå¿ èŠã§ããã°ã¢ããã°ã¬ãŒãããã«ã¯ä»¥äžã®ã³ãã³ããå®è¡ããŸãã
pip show certifi
pip install certifi --upgrade
åºæ¬çãªäœ¿ãæ¹: `certifi.where()`
certifi
ã©ã€ãã©ãªã®æãåºæ¬çãªæ©èœã¯ãã€ã³ã¹ããŒã«ãããCAãã³ãã«ãã¡ã€ã« (cacert.pem
) ã®ãã¹ãååŸããããšã§ãããã㯠certifi.where()
é¢æ°ã䜿ã£ãŠè¡ããŸãã
import certifi
# CAãã³ãã«ãã¡ã€ã«ã®ãã¹ãååŸ
ca_bundle_path = certifi.where()
print(f"Certifi CA Bundle Path: {ca_bundle_path}")
# åºåäŸ (ç°å¢ã«ãã£ãŠãã¹ã¯ç°ãªããŸã):
# Certifi CA Bundle Path: /path/to/your/python/env/lib/python3.x/site-packages/certifi/cacert.pem
ãã®ååŸãããã¹ã¯ãSSL蚌ææžã®æ€èšŒã«CAãã³ãã«ãã¡ã€ã«ãæ瀺çã«æå®ããå¿
èŠãããå Žåã«äœ¿çšã§ããŸããäŸãã°ãæšæºã©ã€ãã©ãªã® ssl
ã urllib.request
ã䜿ãå Žåãªã©ã該åœããŸãã
import ssl
import urllib.request
import certifi
# certifi ãæäŸããCAãã³ãã«ã䜿ã£ãŠSSLContextãäœæ
context = ssl.create_default_context(cafile=certifi.where())
# äœæããã³ã³ããã¹ãã䜿ã£ãŠHTTPSãªã¯ãšã¹ããéä¿¡
url = "https://www.python.org"
try:
with urllib.request.urlopen(url, context=context) as response:
print(f"Status Code: {response.getcode()}")
# print(response.read().decode('utf-8')[:200]) # ã³ã³ãã³ãã®äžéšã衚瀺
except urllib.error.URLError as e:
print(f"Error accessing {url}: {e}")
ãŸããã³ãã³ãã©ã€ã³ããçŽæ¥ãã¹ã確èªããããšãã§ããŸãã
python -m certifi
# åºåäŸ: /path/to/your/python/env/lib/python3.x/site-packages/certifi/cacert.pem
éå»ã®ããŒãžã§ã³ãšã®äºææ§: 以åã®ããŒãžã§ã³ã§ã¯ certifi.old_where()
ãšããé¢æ°ãååšããæå³çã«å€ãïŒ1024ãããéµãå«ãïŒèšŒææžãè¿œå ãããã³ãã«ã®ãã¹ãè¿ãæ©èœããããŸããããã»ãã¥ãªãã£äžã®çç±ããããã¯éæšå¥šãšãªããçŸåšã¯ certifi.where()
ã®ãšã€ãªã¢ã¹ïŒå¥åïŒãšãªã£ãŠããŸããå€ãã³ãŒãã移è¡ããããã«äžæçã«æ®ãããŠããŸããããæ°ããã³ãŒãã§ã¯å¿
ã certifi.where()
ã䜿çšããŠãã ããã
`requests` ã©ã€ãã©ãªãšã®é£æº ð€
åè¿°ã®éããrequests
ã©ã€ãã©ãªã¯ certifi
ãšå¯æ¥ã«é£æºããŠããŸããcertifi
ãã€ã³ã¹ããŒã«ãããŠããç°å¢ã§ã¯ãrequests
ã¯ããã©ã«ã㧠certifi.where()
ãæãCAãã³ãã«ãã¡ã€ã«ã䜿çšããŠSSL蚌ææžã®æ€èšŒãè¡ããŸãã
import requests
try:
# requests ã¯èªåçã« certifi ã® CA ãã³ãã«ã䜿çšãã (verify=True ãããã©ã«ã)
response = requests.get("https://httpbin.org/get")
response.raise_for_status() # ãšã©ãŒãããã°äŸå€ãçºçããã
print("Request successful!")
# print(response.json()) # ã¬ã¹ãã³ã¹å
容ã衚瀺
except requests.exceptions.SSLError as e:
print(f"SSL Error: {e}")
except requests.exceptions.RequestException as e:
print(f"Request failed: {e}")
éåžžãrequests
ã䜿ãéã« certifi
ã®ãã¹ãæ瀺çã«æå®ããå¿
èŠã¯ãããŸãããããããäœããã®çç±ã§ç¹å®ã®CAãã³ãã«ãã¡ã€ã«ã䜿çšãããå Žåã¯ãverify
ãã©ã¡ãŒã¿ã«ãã®ãã¡ã€ã«ã®ãã¹ãæååã§æå®ããŸãã
import requests
import certifi
# æ瀺çã« certifi ã® CA ãã³ãã«ãæå®ããå Žå (éåžžã¯äžèŠ)
ca_bundle = certifi.where()
response = requests.get("https://httpbin.org/get", verify=ca_bundle)
print(f"Using CA Bundle: {ca_bundle}")
# å¥ã®ã«ã¹ã¿ã CA ãã³ãã«ãã¡ã€ã«ã䜿çšããå Žå
custom_ca_bundle_path = "/path/to/your/custom/ca_bundle.pem"
try:
response = requests.get("https://internal.example.com", verify=custom_ca_bundle_path)
print("Request with custom CA bundle successful!")
except FileNotFoundError:
print(f"Custom CA bundle not found at: {custom_ca_bundle_path}")
except requests.exceptions.SSLError as e:
print(f"SSL Error with custom CA bundle: {e}")
except requests.exceptions.RequestException as e:
print(f"Request failed with custom CA bundle: {e}")
ç°å¢å€æ° REQUESTS_CA_BUNDLE
ãèšå®ããããšã§ããrequests
ã䜿çšããCAãã³ãã«ãã¡ã€ã«ãæå®ã§ããŸãããã®ç°å¢å€æ°ãèšå®ãããŠããå Žåãverify=True
ã§ãã£ãŠãããã®ãã¹ã®ãã¡ã€ã«ãåªå
çã«äœ¿çšãããŸãã
蚌ææžã®æŽæ° ð
ã«ãŒã蚌ææžã¯ãã»ãã¥ãªãã£ãç¶æããããã«å®æçã«æŽæ°ããããšãéåžžã«éèŠã§ããå€ã蚌ææžãªã¹ãã䜿ãç¶ãããšã以äžã®ãããªåé¡ãçºçããå¯èœæ§ããããŸãã
- æ°ããä¿¡é Œã§ããèªèšŒå±ã«ãã£ãŠçºè¡ããã蚌ææžãæã€ãŠã§ããµã€ãã«æ¥ç¶ã§ããªããªãã
- ã»ãã¥ãªãã£äžã®åé¡ãçºèŠãããå€ãã«ãŒã蚌ææžãä¿¡é Œãç¶ããŠããŸããæœåšçãªãªã¹ã¯ã«æãããã
- ã«ãŒã蚌ææžã®æå¹æéåãã«ããæ¥ç¶ãšã©ãŒãïŒäŸ: 2021幎9æã«ã¯ Let’s Encrypt ã®å€ãã«ãŒã蚌ææžã§ãã “DST Root CA X3” ãæéåããšãªããå€ãã¯ã©ã€ã¢ã³ãã§åé¡ãçºçããŸãããïŒ
certifi
ã®æŽæ°ã¯éåžžã«ç°¡åã§ããpip
ã䜿ã£ãŠã¢ããã°ã¬ãŒãããã ãã§ãã
pip install certifi --upgrade
ããã«ãããcertifi
ããã±ãŒãžèªäœãææ°çã«ãªããããã«å«ãŸãã cacert.pem
ãã¡ã€ã«ãææ°ã®Mozilla CAãã³ãã«ã«æŽæ°ãããŸãã
ã¢ããªã±ãŒã·ã§ã³ã®ãããã€ããã»ã¹ãCI/CDãã€ãã©ã€ã³ã«ãcertifi
ãå®æçã«æŽæ°ããã¹ããããå«ããããšã匷ãæšå¥šããŸããð
ð¡ ãã¹ããã©ã¯ãã£ã¹
äŸåé¢ä¿ç®¡çããŒã«ïŒpip-tools
ã Poetry
, PDM
ãªã©ïŒã䜿çšããŠãcertifi
ãå«ãäŸåã©ã€ãã©ãªã®ããŒãžã§ã³ã管çããå®æçã«æŽæ°ããããã«ããŸãããã
# pip-tools ã䜿ã£ãŠããå Žåã®äŸ
pip-compile --upgrade requirements.in
pip-sync requirements.txt
泚æç¹ãšãã©ãã«ã·ã¥ãŒãã£ã³ã° ð§
SSL: CERTIFICATE_VERIFY_FAILED ãšã©ãŒ
Pythonã§HTTPSãªã¯ãšã¹ããè¡ã£ãéã« [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed
ãšãããšã©ãŒã«ééããããšããããŸããããã¯ãã¯ã©ã€ã¢ã³ãïŒPythonã¢ããªã±ãŒã·ã§ã³ïŒããµãŒããŒã®SSL蚌ææžãæ€èšŒã§ããªãã£ãããšãæå³ããŸããäž»ãªåå ãšããŠã¯ä»¥äžãèããããŸãã
- å€ã
certifi
: CAãã³ãã«ãå€ãããµãŒããŒèšŒææžãçºè¡ããèªèšŒå±ãå«ãŸããŠããªãã- 解決ç:
pip install certifi --upgrade
ã§certifi
ãæŽæ°ããã
- 解決ç:
- èªå·±çœ²å蚌ææžãŸãã¯ãã©ã€ããŒãCA: ãµãŒããŒãèªå·±çœ²å蚌ææžããå
¬çã«ä¿¡é ŒãããŠããªããã©ã€ããŒãèªèšŒå±ã«ãã£ãŠçºè¡ããã蚌ææžã䜿çšããŠããã
- 解決ç:
- ãµãŒããŒç®¡çè ã«é£çµ¡ããŠãå ¬çã«ä¿¡é Œããã蚌ææžãååŸããŠãããã
- ä¿¡é Œã§ããããšãããã£ãŠããå Žåã¯ããã®èšŒææžãŸãã¯ãã©ã€ããŒãCAã®ã«ãŒã蚌ææžã
requests
ã®verify
ãã©ã¡ãŒã¿ã«æå®ããã - ïŒéæšå¥šïŒéçºç°å¢ãªã©éå®çãªç¶æ³äžã§ãäžæçã«æ€èšŒãç¡å¹ã«ãã (
verify=False
)ã
- 解決ç:
- äŒæ¥å
ãããã·/ãã¡ã€ã¢ãŠã©ãŒã«ã«ããSSLã€ã³ã¹ãã¯ã·ã§ã³: äŒæ¥ãããã¯ãŒã¯å
ãªã©ã§ããããã·ãµãŒããŒãSSL/TLSéä¿¡ã埩å·ã»æ€æ»ããç¬èªã®èšŒææžã§åæå·åããŠããå ŽåïŒSSLã€ã³ã¹ãã¯ã·ã§ã³/SSLã€ã³ã¿ãŒã»ããïŒããã®å Žåããããã·ãçºè¡ãã蚌ææžãä¿¡é Œããå¿
èŠããããŸãã
- 解決ç: ãããã¯ãŒã¯ç®¡çè
ã«é£çµ¡ãããããã·ã䜿çšããŠããã«ãŒã蚌ææžïŒãŸãã¯äžé蚌ææžïŒãå
¥æãããããCAãã³ãã«ãšããŠæå®ãããç°å¢å€æ°
REQUESTS_CA_BUNDLE
ãSSL_CERT_FILE
ãèšå®ããããrequests.get(..., verify='/path/to/proxy/cert.pem')
ã®ããã«æå®ããã
- 解決ç: ãããã¯ãŒã¯ç®¡çè
ã«é£çµ¡ãããããã·ã䜿çšããŠããã«ãŒã蚌ææžïŒãŸãã¯äžé蚌ææžïŒãå
¥æãããããCAãã³ãã«ãšããŠæå®ãããç°å¢å€æ°
- ã·ã¹ãã æå»ã®ãã: ã¯ã©ã€ã¢ã³ãPCã®ã·ã¹ãã æå»ã倧å¹
ã«ãããŠãããšã蚌ææžã®æå¹æéã®æ€èšŒã«å€±æããããšãããã
- 解決ç: ã·ã¹ãã æå»ãæ£ç¢ºã«åããããNTPãµãŒããŒãšåæãããã®ãäžè¬çã
- ãµãŒããŒèšå®ã®åé¡: ãµãŒããŒåŽã§èšŒææžãã§ãŒã³ãæ£ããèšå®ãããŠããªãïŒäžé蚌ææžãäžè¶³ããŠãããªã©ïŒã
- 解決ç: ãµãŒããŒç®¡çè ã«é£çµ¡ããŠèšå®ã確èªããŠãããããªã³ã©ã€ã³ã®SSLãã§ãã¯ããŒã«ïŒäŸ: SSL Labs Server TestïŒã§ç¢ºèªããããšãæå¹ã
Windowsç°å¢ã§ã®æ³šæç¹
Windowsã§ã¯ãOSèªäœã®èšŒææžã¹ãã¢ãš certifi
ã管çãã蚌ææžã¹ãã¢ã¯å¥åã«æ±ãããŸããOSã®èšŒææžã¹ãã¢ã«äŒæ¥å
ã®ã«ãŒã蚌ææžãªã©ãè¿œå ããŠããããã©ã«ãã§ã¯Pythonã® requests
ãªã©ã¯ãããåç
§ããŸããã
ããWindowsã®èšŒææžã¹ãã¢ã«ãã蚌ææžãPythonã¢ããªã±ãŒã·ã§ã³ããå©çšãããå Žåãpython-certifi-win32
ãšããã©ã€ãã©ãªãã€ã³ã¹ããŒã«ããæ¹æ³ããããŸãããã®ã©ã€ãã©ãªã¯ãcertifi
ãããŒããããéã«ã¢ã³ããŒããããé©çšããWindowsã®èšŒææžã¹ãã¢ã®å
容ã certifi
ã®CAãã³ãã«ã«ïŒäžæçã«ïŒããŒãžãããããªæåãããŸãã
pip install python-certifi-win32
ã€ã³ã¹ããŒã«ããã ãã§ãimport requests
ãªã©ãããéã«èªåçã«Windowsã®èšŒææžã¹ãã¢ãèæ
®ãããããã«ãªããŸãããã ããããã¯Windowsåºæã®è§£æ±ºçã§ããããšã«æ³šæãå¿
èŠã§ãã
ã«ã¹ã¿ã 蚌ææžã®è¿œå
åè¿°ã®éããcertifi
ã¯çŽæ¥çãªèšŒææžã®è¿œå ã»åé€ããµããŒãããŸãããã«ã¹ã¿ã 蚌ææžã䜿ãããå Žåã¯ã以äžã®æ¹æ³ãäžè¬çã§ãã
- `verify` ãã©ã¡ãŒã¿ã§æå®:
requests.get(url, verify='/path/to/custom_cert.pem')
- ç°å¢å€æ°ã§æå®:
REQUESTS_CA_BUNDLE
:requests
ã䜿çšããCAãã³ãã«ãæå®ãSSL_CERT_FILE
: Pythonã®ssl
ã¢ãžã¥ãŒã«ãåç §ããããã©ã«ãã®CAãã¡ã€ã«ãã¹ãæå®ã
certifi
ã®cacert.pem
ã«ã«ã¹ã¿ã 蚌ææžã®å 容ãè¿œèšãããã¡ã€ã«ãäœæãããã®ãã¹ãæå®ããããšãå€ãã§ãã# certifiã®ãã³ãã«ãšã«ã¹ã¿ã 蚌ææžãçµåããäŸ cat $(python -m certifi) /path/to/your/custom_cert.pem > combined_bundle.pem export REQUESTS_CA_BUNDLE=/path/to/combined_bundle.pem python your_script.py
- Sessionãªããžã§ã¯ãã§èšå®: è€æ°ã®ãªã¯ãšã¹ãã§åãã«ã¹ã¿ã 蚌ææžã䜿ãå Žåã
requests.Session
ãªããžã§ã¯ãã䜿ããšå¹ççã§ããimport requests session = requests.Session() session.verify = '/path/to/custom_cert.pem' response1 = session.get('https://internal.example.com/api1') response2 = session.get('https://internal.example.com/api2')
ã»ãã¥ãªãã£ã«ã€ã㊠ð¡ïž
certifi
èªäœã¯ãä¿¡é Œã§ããCA蚌ææžã®ãªã¹ããæäŸãããšããã·ã³ãã«ãªåœ¹å²ã®ãããã©ã€ãã©ãªèªäœã«è€éãªè匱æ§ãæœãå¯èœæ§ã¯æ¯èŒçäœããšèããããŸããããããã»ãã¥ãªãã£ã«ãããŠéèŠãªåœ¹å²ãæ
ã£ãŠããããã以äžã®ç¹ã«æ³šæãå¿
èŠã§ãã
- åžžã«ææ°çã䜿çšãã: æãéèŠãªã®ã¯ã
certifi
ãåžžã«ææ°ã®ç¶æ ã«ä¿ã€ããšã§ããå€ãããŒãžã§ã³ã䜿ãç¶ãããšãæ¢ç¥ã®è匱æ§ãæã€å¯èœæ§ã®ããã«ãŒã蚌ææžãä¿¡é Œãç¶ããããæ°ãã«ä¿¡é ŒãããCAã®èšŒææžãå«ãŸããŠããªãã£ãããããªã¹ã¯ããããŸãã - è匱æ§æ
å ±ã®ç¢ºèª: Snyk ã GitHub Advisory Database ãªã©ã®è匱æ§ããŒã¿ããŒã¹ã§ã
certifi
ã«é¢é£ããè匱æ§æ å ±ãå ±åãããŠããªããå®æçã«ç¢ºèªããããšãæå¹ã§ããéå»ã«ã¯ãç¹å®ã®ã«ãŒã蚌ææžã®ä¿¡é Œæ§ã«é¢ããåé¡ïŒã³ã³ãã©ã€ã¢ã³ã¹éåãªã©ïŒããã該åœãã蚌ææžããã³ãã«ããåé€ããããšãã£ãæŽæ°ãè¡ãããŠããŸãïŒäŸ: 2024幎ã®GLOBALTRUSTã«ãŒã蚌ææžã®åé€ïŒããããã®æŽæ°ã«å¯Ÿå¿ããããã«ããææ°çãžã®è¿œåŸãéèŠã§ãã - 1024ãããéµã®èšŒææž: ãã€ãŠã¯1024ãããéµã®ã«ãŒã蚌ææžãå«ãŸããŠããŸããããçŸåšã§ã¯åŒ·åºŠãäžååãšãããŠãããMozillaã®CAãã³ãã«ãããåé€ãããŠããŸãã
certifi
ãããã«è¿œåŸããŠãããå€ãããŒãžã§ã³ (certifi.old_where()
ãæå¹ã ã£ãæ代) ã®ãããªåŒ±ãéµã®èšŒææžã¯å«ãŸããŠããŸããã
ðš éå»ã®è匱æ§äŸ (åè)
ãããŸã§äŸã§ãããéå»ã«ã¯ä»¥äžã®ãããªåé¡ã«é¢é£ã㊠certifi
ãæŽæ°ãããããšããããŸãã
- CVE-2024-39689 (2024幎7æé ): GLOBALTRUST ã®ã«ãŒã蚌ææžãã³ã³ãã©ã€ã¢ã³ã¹åé¡ã«ãã Mozilla ã®ä¿¡é Œãªã¹ãããåé€ãããåããããã
certifi
ã®ããŒãžã§ã³ 2024.7.4 ã§è©²åœèšŒææžãåé€ãããŸããã - ç¹å®ã®ããŒãžã§ã³ç¯å²ã§ã蚌ææžãã§ãŒã³ã®æ€èšŒã«é¢ããåé¡ããç¹å®ã®èšŒææžã®äžé©åãªæ€èšŒã«é¢ããè匱æ§ãå ±åãããããšããããŸã (äŸ: CVE-2023-37920, CVE-2022-23491)ã
ãããã®åé¡ã¯ãcertifi
ãææ°çã«ã¢ããããŒãããããšã§ä¿®æ£ãããŠããŸããäŸåé¢ä¿ã¹ãã£ã³ããŒã«ãªã©ã掻çšããåžžã«å®å
šãªããŒãžã§ã³ã䜿çšããããã«å¿ãããŸãããã
ãŸãšã ð
certifi
ã¯ãPythonã¢ããªã±ãŒã·ã§ã³ã§å®å
šãªHTTPSéä¿¡ãè¡ãäžã§ãçžã®äžã®åæã¡ãšãèšããéèŠãªã©ã€ãã©ãªã§ãããã®äž»ãªåœ¹å²ãšå©ç¹ããŸãšãããšä»¥äžã®ããã«ãªããŸãã
- â Mozillaã管çããä¿¡é Œæ§ã®é«ãã«ãŒã蚌ææžïŒCAãã³ãã«ïŒãæäŸããŸãã
- â OSç°å¢ã«äŸåããªããäžè²«ãã蚌ææžæ€èšŒã®åºç€ãæäŸããã¢ããªã±ãŒã·ã§ã³ã®ç§»æ€æ§ãé«ããŸãã
- â
requests
ãªã©ã®äž»èŠãªHTTPã¯ã©ã€ã¢ã³ãã©ã€ãã©ãªãšé£æºããããã©ã«ãã§å®å šãªèšŒææžæ€èšŒãå®çŸããŸãã - â
pip
ã§ç°¡åã«ã€ã³ã¹ããŒã«ã»æŽæ°ã§ããåžžã«ææ°ã®ä¿¡é Œã§ãã蚌ææžãªã¹ããç¶æããããšãå¯èœã§ãã
SSL/TLS蚌ææžã®æ€èšŒã¯ãã€ã³ã¿ãŒãããäžã®éä¿¡ãå®å
šã«ä¿ã€ããã®åºæ¬çãªèŠçŽ ã§ããcertifi
ãé©åã«å©çšããåžžã«ææ°ã®ç¶æ
ã«ä¿ã€ããšã§ãäžéè
æ»æãªã©ã®ã»ãã¥ãªãã£ãªã¹ã¯ããã¢ããªã±ãŒã·ã§ã³ãä¿è·ããããšãã§ããŸãã
Pythonã§ãããã¯ãŒã¯éä¿¡ãè¡ãã¢ããªã±ãŒã·ã§ã³ãéçºããéã¯ãcertifi
ã®ååšãšåœ¹å²ãç解ããå®å
šãªéä¿¡ã®å®è£
ãå¿ãããŸãããïŒ âšð
ã³ã¡ã³ã