2019년 4월 24일 수요일

회사 프록시 서버는 DFAST의 reference database 다운로드도 어렵게 한다

비슷한 제목의 글을 연일 작성하게 되었다.
회사 프록시 서버는 ....을 어렵게 한다.
https://로 시작하는 곳을 접속하여 파일을 가져오는 것을 어렵게 하는 문제를 4월 초부터 하나씩 해결을 해 나갔다. 이제는 거의 다 해결을 했다고 생각했는데, 파이썬 코드 안에서 urllib 모듈을 사용하여 파일을 다운로드하는 request 메소드의 실행에서 문제가 벌어졌다. 라이브러리, 모듈, 함수, 메소드에 대한 정확한 정의는 일단 무시하도록 하자. 나는 파이썬 코드를 직접 쓰는 사람이 아니고 파이썬 응용프로그램을 설치하고 사용만 하는 사람이므로.

미생물 유전체 주석화 파이프라인의 대명사인 prokka와 병행하여 사용할 다른 프로그램을 검토 및 테스트하는 중에 벌어진 일이다. 일본에서 개발한 DFAST의 참조 데이터베이스를 설치하는 과정에서 또다시 SSL 인증 불가 문제가 드러난 것이다. wget/curl/pip를 실행하는 과정에서 SSL 인증을 건너뛰는 방법은 이제 충분히 알아낸 상태이지만, 코드 내에서 실행되는 함수 수준에서 벌어지는 에러라면 어떻게 할 것인가?

# python scripts/file_downloader.py --protein dfast
No handlers could be found for logger "dfc.utils.path_util"
Downloading DFAST reference. Files will be written into '/usr/local/apps/dfast_core/db/protein'
Traceback (most recent call last):
  File "scripts/file_downloader.py", line 169, in <module>
    retrieved_file = retrieve_dfast_reference(db_name, out_dir)
  File "scripts/file_downloader.py", line 74, in retrieve_dfast_reference
    request.urlretrieve(target_url, output_file)
  File "/usr/lib64/python2.7/urllib.py", line 94, in urlretrieve
    return _urlopener.retrieve(url, filename, reporthook, data)
  File "/usr/lib64/python2.7/urllib.py", line 240, in retrieve
    fp = self.open(url, data)
  File "/usr/lib64/python2.7/urllib.py", line 208, in open
    return getattr(self, name)(url)
  File "/usr/lib64/python2.7/urllib.py", line 437, in open_https
    h.endheaders(data)
  File "/usr/lib64/python2.7/httplib.py", line 1037, in endheaders
    self._send_output(message_body)
  File "/usr/lib64/python2.7/httplib.py", line 881, in _send_output
    self.send(msg)
  File "/usr/lib64/python2.7/httplib.py", line 843, in send
    self.connect()
  File "/usr/lib64/python2.7/httplib.py", line 1260, in connect
    server_hostname=sni_hostname)
  File "/usr/lib64/python2.7/ssl.py", line 348, in wrap_socket
    _context=self)
  File "/usr/lib64/python2.7/ssl.py", line 609, in __init__
    self.do_handshake()
  File "/usr/lib64/python2.7/ssl.py", line 831, in do_handshake
    self._sslobj.do_handshake()
IOError: [Errno socket error] [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:618)

문제가 되는 것은 file_downloader.py 스크립트의 다음 줄이다.

    from urllib import request
    ...
    request.urlretrieve(target_url, output_file)

SSL verification 여부를 함수의 인자에 줄 수 있는 것 같지는 않다. pip 말고 파이썬 자체가 참조하는 인증서 번들 위치를 찾아서 Somansa의 루트 인증서 파일을 넣어도 될 것이다. 그런데 어디인지를 잘 모르겠다. 인증서 번들이라 해도 중간 단계 인증서는 없으므로 소만사에서 발급한 것 하나면 충분하다.

문제 해결 답안의 보물창고인 StackOverflow에서 힌트를 발견하였다. PYTHONHTTPSVERIFY 환경변수를 0으로 놓으면 된다.

urllib and "SSL: CERTIFICATE_VERIFY_FAILED" Error

# PYTHONHTTPSVERIFY=0 python scripts/file_downloader.py --protein dfast

환경변수 설정과 명령어를 한 줄에 놓는 것은 처음에는 매우 어색하게 느껴졌었다. 그러나 지금은 매우 익숙해졌다. 여기에서 PYTHONHTTPSVERIFY는 환경변수인가 쉘변수인가? 여기여기를 방문하여 잠깐 생각해 보도록 하자.

2019일 4월 25일 업데이트

HMMer와 RPS-BLAST 데이터베이스를 다운로드하는 과정에서 또다시 문제가 발생하였다.

# python scripts/file_downloader.py --cdd Cog --hmm TIGR

다운로드한 파일의 압축을 풀고 hmmpress를 실시하는 등의 후처리가 돌아가야 이 작업이 완료된다. 그런데 다운로드 자체가 원활하지 않아서 파일을 받다가 만 상태로 다음 과정으로 진행하는 것이다. 그래서 소스 코드를 참조하여 완전한 형태의 두 파일을 wget으로 미리 받은 다음(중간에 접속이 끊겨도 재전송이 가능), 다운로드 명령을 무력화한 소스 코드를 재실행하는 것으로 마무리하였다. 파이썬을 잘 알지 못하는 상태에서 소스를 고친다는 것이 대단히 부담스러웠다. 한 일이라고는 '#'를 소스 내 두 줄의 시작 부분에 삽입한 것이 전부였지만.

댓글 없음: