-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
[docs] Git 민감 정보 노출 문제 해결하기 (#26)
- Loading branch information
Showing
1 changed file
with
118 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
--- | ||
title: Git 민감 정보 노출 문제 해결하기 | ||
slug: Git-submodule-private | ||
authors: [huchu] | ||
tags: [git, collaboration] | ||
--- | ||
|
||
## 들어가기 | ||
|
||
트립드로우 팀 프로젝트에서 협업을 진행하면서 공개되면 안 되는 민감(private) 정보가 외부에 노출될 뻔한 상황이 자주 있었습니다. | ||
|
||
Git submodule을 사용하면서 Gradle에 copy 설정을 추가한 것이 문제의 원인이었습니다. | ||
|
||
민감 정보가 외부에 노출되지 않도록 하기 위해 이를 해결하려고 시도했습니다. | ||
|
||
# 민감 정보 노출 문제 | ||
|
||
## 배경 | ||
트립드로우의 백엔드 팀은 Git submodule을 사용하고 있습니다. | ||
|
||
![image](https://github.com/woowacourse-teams/2023-trip-draw/assets/106813090/f948787e-1ceb-47d4-bb5a-f5a7a37b13fb) | ||
|
||
submodule 내부에는 여러 application.yml 파일들이 있습니다. 이 yml 파일들은 profile로 구분되고 외부로 노출되면 안 되는 private 한 환경변수들을 포함하고 있습니다. | ||
|
||
![](https://velog.velcdn.com/images/153plane/post/3d4664a3-383e-4d7e-ac75-809bc9b1591b/image.png) | ||
|
||
|
||
애플리케이션을 실행할 때는 `-Dspring.profiles.active={profile_name}` 설정으로 애플리케이션에 적합한 profile을 매핑합니다. | ||
|
||
그렇다면 submodule에 있는 application.yml 파일을 어떻게 애플리케이션 내부로 불러오고 있을까요? | ||
|
||
그것은 build.gradle 파일을 보면 알 수 있습니다. | ||
|
||
![image](https://github.com/woowacourse-teams/2023-trip-draw/assets/106813090/8ca0d1b7-11e2-4822-8efc-7c5a0abe9112) | ||
|
||
build.gradle 을 보면, build 시 submodule 디렉터리에 있는 파일들을 모두 `src/main/resources` 로 copy 하는 로직이 있습니다. | ||
|
||
따라서 코드를 build 하고 jar 를 실행할 때 submodule에 있는 yml 파일들을 사용할 수 있는 것입니다. | ||
|
||
이 방법은 편리하지만 심각한 문제를 갖고 있습니다. | ||
|
||
## 문제 | ||
어느 환경에서든 build 시 submodule 디렉터리에 있는 yml 파일들이 모두 resources 로 복사되는 것이 문제입니다. | ||
|
||
![image](https://github.com/woowacourse-teams/2023-trip-draw/assets/106813090/96cf9d21-1fe8-4dbf-b6ca-575cd16df98b) | ||
|
||
위처럼 local 환경에서 테스트 코드를 실행할 때에도 yml 파일들이 복사됩니다. | ||
|
||
submodule 에 yml 파일들을 분리해둔 이유는 이 yml 파일들이 private 정보들을 포함하고 있기 때문입니다. | ||
|
||
하지만 이 파일들을 resources 에 복사해서 사용한다면, **다른 코드에 대한 commit & push 를 진행할 때 yml 파일도 함께 포함될 가능성이 있습니다**. | ||
|
||
현재 프로젝트에서는 `.gitignore` 에 private files 들을 등록해놓고 이를 방지하고 있습니다. | ||
|
||
![image](https://github.com/woowacourse-teams/2023-trip-draw/assets/106813090/ff4f42b7-5814-4ad0-8985-5fa4eab3b1f3) | ||
|
||
다만, 새로운 yml 파일이 추가되거나 기존 yml 파일의 이름을 수정할 경우 `.gitignore` 에 이러한 변경사항을 반영하는 것을 잊을 수 있습니다. | ||
|
||
**사람의 실수(휴먼 에러)로 인해 민감 정보가 노출되는 매우 큰 사고를 야기할 수 있는 구조**입니다. | ||
|
||
실제로 협업을 진행하면서 팀원들이 `혹시 내가 yml까지 push했나?` 하고 불안을 느끼거나, 올라가지 않은 것을 확인하고 안도의 한숨을 내쉬는 모습을 목격했습니다. | ||
|
||
## 해결 | ||
|
||
민감 정보 노출 사고를 막기 위해서는 gradle.build 를 통해 resources에 직접 copy 하는 로직을 사용하지 않아야 합니다. | ||
|
||
동일한 동작을 하면서 보다 안전한 두 가지 방법을 찾았습니다. | ||
|
||
### 1. spring.config.import | ||
|
||
```yml | ||
spring: | ||
config: | ||
import: {yml 파일 경로} | ||
activate: | ||
on-profile: {profile 이름} | ||
``` | ||
spring.config.import 설정을 통해 `src/main/resources` 외부에 위치한 yml 파일을 불러와 사용할 수 있습니다. | ||
|
||
resources 디렉터리에 copy 하지 않아도 되는 방법입니다. | ||
|
||
### 2. config 디렉터리 | ||
![image](https://github.com/woowacourse-teams/2023-trip-draw/assets/106813090/444da9d8-0621-4576-b4e3-b03b60b2d568) | ||
|
||
[Spring 공식문서](https://docs.spring.io/spring-boot/docs/1.5.22.RELEASE/reference/html/boot-features-external-config.html#boot-features-external-config-application-property-files)를 살펴보면, SpringApplication이 로드될 때 yml 파일을 읽는 순서가 명시되어 있습니다. | ||
|
||
1. 현재 디렉터리에 존재하는 `/config` 디렉터리 | ||
2. 현재 디렉터리 | ||
3. classpath 에 존재하는 `/config` 디렉터리 | ||
4. classpath | ||
|
||
classpath 혹은 프로젝트 디렉터리에서 `config` 라는 이름의 디렉터리에 존재하는 yml 파일을 읽는 것을 알 수 있습니다. | ||
|
||
따라서 submodule의 이름을 config 로 설정해둔다면 별다른 import 없이도 yml 파일을 읽게 할 수 있습니다. | ||
|
||
submodule의 이름과 경로를 변경하는 명령어는 다음과 같습니다. | ||
|
||
```shell | ||
git mv /{현재 submodule 경로}/{현재 submodule 이름} /{변경할 submodule 경로}/{변경할 submodule 이름} | ||
``` | ||
|
||
## 선택 | ||
두 번째 방법(/config 디렉터리)을 선택하기로 결정했습니다. | ||
|
||
유지보수에 더 유리하다고 판단했기 때문입니다. | ||
|
||
submodule 디렉터리의 이름을 config로 짓는다면, import를 명시하지 않아도 되는 점이 편리하게 느껴졌습니다. import 경로를 설정하는 것도 관리해야 할 요소가 될 수 있기 때문입니다. | ||
|
||
`git mv` 명령어를 통해 submodule의 위치와 이름을 변경했습니다. | ||
|
||
![](https://velog.velcdn.com/images/153plane/post/f3c2db3c-efd0-40fa-b7dc-37cf4aeb3836/image.png) | ||
|
||
이제 resources 디렉터리 하위에 `config` 라는 이름의 submodule이 존재하고 여기서 yml 파일들이 관리됩니다. | ||
|
||
기존에 build.gradle에 있던 copy 로직은 삭제했습니다. | ||
|
||
더 이상 이 문제로 민감 정보가 노출되지 않게 되었습니다! |