Python SSL 사용

Python SSL 라이브러리 버전 2.7은 지원 중단되었습니다. 대신 최신 버전(현재는 2.7.11)을 사용하세요.

App Engine은 Python 2.7 런타임용 기본 Python SSL 라이브러리를 지원합니다.

SSL 라이브러리 지정

기본 Python SSL을 사용하려면 애플리케이션의 app.yaml에서 libraries 구성에 ssl을 지정하여 이를 사용 설정해야 합니다. 최신 라이브러리 버전(현재는 버전 2.7.11)을 사용해야 합니다. 이 버전은 TLS 버전 1.0, 1.1, 1.2를 지원하며 Python 2.7.11 이상의 SSL 버전에 해당합니다.

libraries:
- name: ssl
  version: latest

기관 인증서 제공

SSL 핸드셰이크를 수행하려면 연결된 인증 기관 인증서가 포함된 파일이 있어야 합니다. 사용 중인 파일을 애플리케이션과 함께 업로드하거나, App Engine에서 제공되는 파일인 /etc/ca-certificates.crt를 사용할 수 있습니다.

SSL 핸드셰이크 수행

Python 2.7 wrap_socket 메소드는 클라이언트의 키와 인증서를 포함하는 두 개의 파일 이름 매개변수를 인수로 사용합니다. App Engine 환경에서는 애플리케이션이 여러 키와 인증서를 동적으로 제공하기 위한 파일을 작성할 수 없기 때문에 여기에 제한이 있습니다. 이 제한을 해결하기 위해 ssl.wrap_socket 메소드의 certfilekeyfile 매개변수는 애플리케이션이 업로드된 애플리케이션 파일 이외의 다른 방법으로 인증서와 키를 저장할 수 있도록 하는 '파일형' 객체가 될 수 있습니다. '파일형' 객체는 전체 인증서를 문자열로 반환하는 '읽기' 메소드가 있는 객체입니다.

  # Example of a dynamic key and cert.
  datastore_record_k = ndb.Key('Employee', 'asalieri', 'Address', 1)
  datastore_record = datastore_record_k.get()
  key_str = datastore_record.key_str
  cert_str = datastore_record.cert
  ssl_server = ssl.wrap_socket(server_sock,
                              server_side=False,
                              keyfile=StringIO.StringIO(key_str),
                              certfile=StringIO.StringIO(cert_str),
                              cert_reqs=ssl.CERT_REQUIRED,
                              ssl_version=ssl.PROTOCOL_SSLv23,
                              ca_certs=CERTIFICATE_FILE)

ssl_version 매개변수는 지정하지 않아도 됩니다. 이 매개변수를 생략할 경우 2.7.11 라이브러리는 기본적으로 PROTOCOL_SSLv23이 됩니다. PROTOCOL_TLSv1, PROTOCOL_TLSv1_1 또는 PROTOCOL_TLSv1_2를 지정할 수도 있습니다.

wrap_socket 메소드의 App Engine 구현에는 연결된 인증 기관 인증서가 포함된 특수 파일을 지정하는 데 사용되는 필수 매개 변수 ca_certs가 포함되어 있습니다.

인증서 유효성 검사

'중간자' 공격과 같은 특정 보안 취약점을 방지하려면 앱에서 인증서의 유효성을 검사해야 합니다.

방법은 다음과 같습니다.

  1. app.yaml 파일을 수정하여 환경 변수 PYTHONHTTPSVERIFY1로 설정해서 추가합니다.

     env_variables:
       PYTHONHTTPSVERIFY: 1
    
  2. 앱을 다시 배포합니다.

app.yaml에서 인증서 유효성 검사를 지정하는 대신 다음과 같이 SSL 핸드셰이크를 성공적으로 수행한 후에 SSL 라이브러리를 명시적으로 호출하여 유효성 검사를 수행할 수도 있습니다.

    ssl.match_hostname(ssl_server.getpeercert(), 'a.hostname.com')

위의 코드에서는 Python 3.2에서 App Engine Python 2.7.11 SSL 모듈의 일부로 백포팅된 match_hostname 기능을 사용합니다. 이 호출은 피어가 제공한 인증서가 피어의 인증서에 지정된 호스트 중 하나와 일치하는지 확인합니다.

dev_appserver에서 작업

urlfetch API를 사용하여 HTTPS 요청을 실행할 수 있으며, urlfetch를 사용하는 경우 httplib를 사용한 Dev_server의 인증서 유효성 검사 동작은 프로덕션 App Engine 환경과 동일합니다. Dev_appserver는 소켓을 사용한 요청을 지원하지 않습니다.