grape

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

웹 프로그래밍/Django

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

grape-story 2021. 6. 6. 15:11

시크릿 키란? (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": "<Your Django SECRET KEY>"
}

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

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

 

03. 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 파일 위치를 명시

with open(secret_file) as f:
    secrets = json.loads(f.read())

def get_secret(setting):
    """비밀 변수를 가져오거나 명시적 예외를 반환한다."""
    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에 사용하므로 써 외부의 노출을 막아 준다. 

 

04. gitignore 파일에 추가

# .gitignore 파일

secrets.json

 

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

 

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

. gitignore 파일이란?

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

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

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

 

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

  • IDE tool과 관련된 설정 파일
  • 언어의 빌드 결과물, 로그, 패키지 관련 파일
  • 그 외 프로젝트에서 사용자가 제외하기 원하는 파일 등등.. 

 

정리

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

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

 

 

참고

https://lhy.kr/django-secrets

 

Django에서 비밀 값(secrets) 관리하기

장고에서 사용하는 AWS 시크릿 코드, 장고 시크릿 키 등의 비밀 값들은 프로젝트 코드에 포함되면 안됩니다. 이러한 비밀 값들을 별도의 JSON파일로 보관하고, 해당 값들을 장고에서 불러오는 방

lhy.kr

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

 

Django - settings.py 의 SECRET_KEY 변경 및 분리하기 · 초보몽키의 개발공부로그

Django - settings.py 의 SECRET_KEY 변경 및 분리하기 11 Jul 2017 | python Django settings secret key Two Scoops of Django 5장을 읽고 연습한 내용을 정리한 글입니다. 더 좋은 방법이 있거나, 잘못된 부분이 있으면 편하

wayhome25.github.io

 

Comments