그동안 프로젝트를 하면서 SECRET_KEY를 아무렇지 않게 Github에 push했다.
하지만 SECRET_KEY는 django에서 보안 기능에 활용되는 값이기 때문에 외부에 노출되면 안된다.
SECRET_KEY는 django 프로젝트를 생성 시 50자의 랜덤 문자로 자동 생성되고, 예측할 수 없는 고유의 값으로 생성이 된다.
따라서 최초에 settings.py에 생성되는 SECRET_KEY를 외부에서 별도의 JSON 파일 또는 라이브러리(ex - environ) 파일로 저장하여 보관하고, 해당 값들을 django에서 불러오는 방법으로 관리해야 한다.
만약 SECRET_KEY를 settings.py 외부에서 저장하고 django에서 불러오지 않을 경우 프로젝트가 생성되지 않기 때문에 외부에서 별도의 파일 or 라이브러리로 저장한 SECRET_KEY를 django에 불러오는 방법을 알아보았다.
Django 공식문서에 소개된 SECRET_KEY가 사용되는 용도는 다음과 같다.
분리하는 방법으로는 환경 변수를 이용한 방법과 외부에 저장하는 방법 2가지가 있다.
먼저 환경 변수로 분리하는 방법인데 이 방법은 OS나 Shell에 따라 편집하는 파일이 다르며 팀 프로젝트에서는 적합하지 않은 것 같아 다른 방법인 비밀 파일을 생성하여 키값을 분리하는 방법을 사용할 것이다.
먼저 secrets.json 이라는 파일을 생성하여 안에 SECRET_KEY를 넣어준다.
# secrets.json
{
"SECRET_KEY": "본인의 고유 비밀 키 추가"
}
BASE_DIR의 경로에 secrets.json경로를 합쳐주고, secret_file이라는 변수에 할당한다.
그 다음 secret_file을 open 함수로 열어서 f라는 별칭을 붙여주고, f 파일이 json 형식이기 때문에 json.loads로 f 파일을 read 함수를 사용하여 읽은 데이터를 secrets 라는 변수에 할당한다.
그리고 get_secret 함수에 인자로 가장 아래있는 SECRET_KEY를 가져와 secrets 라는 변수에 SECRET_KEY의 키 값을 가져와서 return한다. 만약 SECRET_KEY에 키 값이 없을 경우 에러메세지를 출력한다.
# settings.py
import os, json
from django.core.exceptions import ImproperlyConfigured
BASE_DIR = Path(__file__).resolve().parent.parent
secret_file = os.path.join(BASE_DIR, 'secrets.json') # secrets.json 파일 위치를 BASE_DIR의 경로와 합침
with open(secret_file) as f:
secrets = json.loads(f.read())
def get_secret(setting, secrets=secrets):
"""비밀 변수를 가져오거나 명시적 예외를 반환한다."""
try:
return secrets[setting]
except KeyError:
error_msg = "Set the {} environment variable".format(setting)
raise ImproperlyConfigured(error_msg)
SECRET_KEY = get_secret("SECRET_KEY")
여기까지 SECRET_KEY를 secrets.json 파일에 분리하여 django에서 키 값을 불러왔다면 github에 push 할 때 secrets.json 파일이 올라가지 않도록 gitignore에 추가해주어서 파일이 올라가지 않게 설정해준다.
# gitignore 파일
secrets.json
만약 SECRET_KEY을 그대로 Github이나 외부에 노출되었다면 Django Secret Key Generator 에서 SECRET_KEY 값을 변경할 수 있다.
다른 방법으로는 아래의 코드를 실행시켜서 랜덤한 50자의 문자열을 생성하는 방법도 있다.
import string, random
# Get ascii Characters numbers and punctuation (minus quote characters as they could terminate string).
chars = ''.join([string.ascii_letters, string.digits, string.punctuation]).replace('\'', '').replace('"', '').replace('\\', '')
SECRET_KEY = ''.join([random.SystemRandom().choice(chars) for i in range(50)])
print(SECRET_KEY)