[Django 02] - 시크릿 키(SECRET_KEY) 분리 설정

[Django 02] - 시크릿 키(SECRET_KEY) 분리 설정

시크릿 키란? (SECRET_KEY)

장고 프로젝트를 생성하면, 기본적으로 메인 폴더에 settings.py가 생성된다. settings.py 안에는 다양한 설정 항목들이 있는데 그중 SECRET_KEY라는 것이 있다. Django 공식문서를 보면 다음과 같이 안내 되어 있다.

- SECRET_KEY의 사용 용도

django.contrib.sessions.backends.cache 이외의 session backend를 사용하고 있거나, 기본 get_session_auth_hash()를 사용하는 모든 sessions

CookieStorage 혹은 FallbackStorage를 사용하는 모든 messages

모든 PasswordResetView

다른 키가 제공되지 않는 암호화 서명 사용 시 사용된다.

"SECRET_KEY 란 특정 django 설치을 위한 비밀 키이며 이는 암호화 서명을 제공하는 데 사용되며 고유하고 예측할 수 없는 값으로 설정해야 한다. "라고 나와 있다. 즉, 암호화 인증에 사용되는 비밀키라는 말이다. - (보안 관리)

django 공식 문서

그리고 SECRET_KEY는 공개하면 안된다 !

공식문서에서 위 문서와 같이 비밀 키가 노출되면 Django의 보안 기능이 상실될 위험성이 있다고 안내되어 있다.

Tip.

SECRET_KEY는 프로젝트 생성 시 자동으로 생성되며 해당 값은 예측할 수 없는 값이며 유일한 값으로 세팅된다. 또한 버전 컨트롤 시스템(Git)에서 제외되어야 하며 만약 외부에 노출 시 보안 위협에 노출될 수 있기 때문에 settings.py 파일이 아닌 외부에 따로 저장해야 한다. SECRET_KEY 말고도 AWS 시크릿 코드 등의 비밀 값들이 있는데 이런 비 밀값들은 프로젝트 코드에 포함되면 안 된다. 이러한 비밀 값들은 별도의 JSON 파일 또는 라이브러리(ex - environ) 파일로 보관하고, 해당 값들을 django에서 불러오는 방법으로 사용한다.

-- SECRET_KEY가 없으면 Django 프로젝트는 실행되지 않는다.

-- 해당 키를 분리하는 방법으로는 환경 변수를 이용한 방법과 외부에 저장하는 방법 2가지가 있다.

환경변수 패턴: SECRET_KEY의 값을 환경변수에 저장하여 참고한다.

비밀파일 패턴: SECRET_KEY의 값을 별도 파일에 저장하여 참고한다.

SECRET_KEY 배포 후 변경 가능 유무

SECRET_KEY 같은 경우 한번쯤은 공개 저장소에 올린 적이 있을 것이다. 하지만 다행히도 배포 후 에도 SECRET_KEY 변경이 가능하다는 글이 있다.

SECRET_KEY는 50자의 랜덤 문자로 구성되어 있는데, Django Secret Key Generator라는 것도 존재하고 혹은 아래의 코드를 실행해서 임의 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)

외부에 저장하는 방법

01. secret.json 생성

- 프로젝트 구조

tistory | | | ㅡㅡ tistory (app 1) | | | |ㅡㅡ __init__.py | |ㅡㅡ asgi.py | |ㅡㅡ settings.py | |ㅡㅡ urls.py | |____ wsgi.py | | | ㅡㅡ blog (app 2) | | | |ㅡㅡㅡㅡㅡ migrations | | | | | |___ __init__.py | |ㅡㅡ __init__.py | |ㅡㅡ admin.py | |ㅡㅡ apps.py | |ㅡㅡ models.py | |ㅡㅡ tests.py | |____ views.py | | | ㅡㅡㅡ db.sqlite3 | ㅡㅡㅡ secrets.json |______ manage.py

프로젝트 구조를 보면 알 수 있듯이 secrets.json 파일을 생성하는데 생성하는 위치는 프로젝트 컨테이너 폴더에서 생성해 주면 된다.

02. secrets.json 내용

{ "SECRET_KEY": "" }

위와 같이 Json 형식에 맞게 settings.py에 생성된 SECRET_KEY를 가져와서 secrets.json 파일에 저장해 준다.

secret_key 이외에 데이터 베이스 ID, PW 값 등등 보안에 문제 될 수 있는 내용 또한 secrets.json 파일에 따로 분리 저장할 수 있다.

03. Settings.py

import os, json BASE_DIR = Path(__file__).resolve().parent.parent secret_file = os.path.join(BASE_DIR, 'secrets.json') # secrets.json 파일 위치를 명시 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")

위 코드를 보면 알 수 있듯이 os, json 모듈을 먼저 import 해준다. 그다음 BASE_DIR 코드를 상위로 올려준다. 그 이유는 파이썬의 코드 동작 순서는 위에서 아래로 동작하기 때문에 먼저 BASE_DIR 현재 최상위 파일 위치(tistory)를 잡아준다.

그다음 secret_file이라는 변수에 screts.json 파일을 담아 준 뒤 해당 파일을 열어서 secrets이라는 변수에 담아 준다.

get_secret 함수를 생성해서 비밀 변수를 가져오거나 예외를 발생시키는 함수를 생성 한 뒤 이를 이용해서 SECRET_KEY에 사용하므로 써 외부의 노출을 막아 준다.

03. . gitignore 파일에 추가

# .gitignore 파일 secrets.josn

.gitignore 파일에 secrets.json 파일을 추가해서 비 밀값들이 커밋에 포함되지 않도록 설정한다.

- gitignore 파일의 위치는 screts.json과 같은 위치에 위치시켜주면 된다.

. gitignore 파일이란?

사용자가 원하지 않는 파일들을 자동적으로 git 커밋 대상에서 제외시켜주는 파일이다.

프로젝트를 진행하다 보면 git에 올려서는 안 되거나 불필요한 파일이 있다.

자동 생성 파일들은 코드만 있으면 그때그때 실행할 수 있어 굳이 Github 용량을 차지할 필요가 없고 또한 보안적으로 중요한 내용이 담긴 파일은 오픈소스로 공개되면 곤란하다. 이때. gitignore파일 안에 이들을 넣어서 관리하는 것이다.

커밋 대상에서 제외시켜야 할 것들

IDE tool과 관련된 설정 파일

언어의 빌드 결과물, 로그, 패키지 관련 파일

그 외 프로젝트에서 사용자가 제외하기 원하는 파일 등등..

-- Window 환경에서 환경 변수 패턴 생성해서 관리하는 방법은 아직 찾지 못했습니다...

아시는 분이 있으면 알려 주세요 ㅠㅠ...

정리

AWS 루트키, SECRET_KEY, DB 정보 등등 보안 관련 이슈들은 배포 전에 분리하는 것이 가장 좋으며 그에 따른 부작용이 발생할 수 있으니 프로젝트 생성 후 처음부터 관리하는 게 좋다.

만약 이미 기존 커밋에 비 밀값들이 포함된 상태라면, 커밋 이후에 비 밀값들을 제외하다록 하여도 기존 커밋에는 내용이 남아 있다. 이때는 git의 reset 명령어로 비밀값이 포함된 커밋을 삭제해야 하며, 또 커밋이 공개 저장소에 push된 상태라면 서비스 프로바이더(페이스북, AWS 등등 ...)에서 해당 비밀값들을 모두 재설정해야 한다.

참고

https://lhy.kr/django-secrets

https://wayhome25.github.io/django/2017/07/11/django-settings-secret-key/

from http://grape-blog.tistory.com/17 by ccl(A) rewrite - 2021-06-06 15:25:47

댓글