민감한 yml 파일을 카톡 대신 동적으로 관리해보자

HwangDo·2025년 1월 26일
0

DevOps

목록 보기
3/3
post-thumbnail

database.yml, .env 업데이트 되었으니 이 파일로 갈아끼워 사용 해 주세요!
라는 카톡을 보내본 적이 있는가?
github actions에서 빌드를 위해 파일이 바뀔 때 마다 base64 인코딩 이후 secrets에 넣어본 경험이 있는가?

나는 굉장히 잦다.. 민감한 파일은 .gitignore 시켜야하고, 버전관리를 할 수 없으니 매번 메신저로 파일을 주고받았다. 그러다보면 멸종되는 파일도 생기고, 귀찮은게 이만 저만이 아니다.

뭐가 불편할까?

  1. 메신저로 변경된 파일을 보내준 뒤, 해당 파일로 일일히 갈아끼우지 않으면 빌드가 안 돌거나 의도치 않은 동작이 된다.
  2. CI/CD를 github actions로 구축해놨다면, yml 파일의 전문을 secrets에 등록해놔야한다. 게다가 base64 인코딩까지 해야한다..!!
  3. 파일의 관리를 모두가 각각 하다보니, 개발 환경이 이전되면 작업을 이어 하기가 어렵다. (파일을 모두 하나하나 파밍해야 한다)

아이디어

그냥 스토리지에 올리면 되는거 아닌가?
라는 생각이 들었다. 이를 위해 S3등의 서비스를 쓸 수도 있겠지만, 나는 WebDAV를 도입해봤다.

WebDAV

WebDAV(Web Distributed Authoring and Versioning)는 웹 사이트를 편집할 수 있는 인터넷 기반 프로토콜입니다. 하이퍼텍스트 전송 프로토콜(HTTP)의 확장으로, HTTPS를 통해 데이터를 업로드하고 다운로드할 수 있습니다.

쉽게 말해, HTTP 프로토콜을 지원하는 웹기반 저장소다. POST 하면 저장, GET 하면 조회, DELETE하면 삭제.. 등등 익숙한 인터페이스다.

왜 WebDAV?

WebDAV는 HTTP를 지원한다. 따라서, curl같은 커맨드로 아주 단순히 파일 연산을 할 수 있다.
curl -X GET https://my-webdav-url/server/database.yml -o database.yml
이 한 줄 만으로 바로 데이터를 가져올 수 있다!

구축해보자

WebDAV는 apache 또는 nginx를 띄워 구축할 수도 있고, 방법은 다양하다.
나는 Docker를 이용해 아주 간편하게 구축해봤다.
나는 1M+의 다운로드가 기록된 ugeek/webdav를 사용했다. 내부적으로는 nginx를 이용해 webdav를 구축해놨다.

  webdav:
    image: ugeek/webdav:arm  # ARM용 이미지
    container_name: webdav-container
    restart: always
    expose:
      - "80"  # 컨테이너가 내부적으로 80 포트 사용
    volumes:
      - $HOME/docker/webdav:/media  # WebDAV 데이터 저장 경로
    environment:
      - USERNAME=!WEBDAV_USERNAME_SECRET!
      - PASSWORD=!WEBDAV_PASSWORD_SECRET!
      - UID=1000
      - GID=1000
      - TZ=Asia/Seoul

docker-compose에 위와 같은 구문을 추가했다. 내 webdav 서버는 M4 실리콘 맥 위에서 돌기에, arm 이미지를 가져왔다.
volumes에는 webdav의 데이터가 저장될 경로를 설정해주면 되고, env에서 username과 password를 잘 설정해주자. 저 Credential을 가지고 접근 권한을 설정해 줄 것이다.


컨테이너를 띄우면 로그인 화면이 뜨고, 위처럼 접속됨을 알 수 있다.

어떻게 쓰나요?

우선 위에서 Username, password를 설정해준 값은 항상 들어가야한다.
예시 몇 가지를 첨부하겠다.

조회
curl -X GET https://my-webdav-url/server/database.yml -o database.yml -u WEBDAV_USERNAME_SECRET:WEBDAV_PASSWORD_SECRET
추가
curl -T ./database.yml https://my-webdav-url/server/database.yml -u WEBDAV_USERNAME_SECRET:WEBDAV_PASSWORD_SECRET
수정(덮어쓰기)
curl -T PUT ./database.yml https://my-webdav-url/server/database.yml -u WEBDAV_USERNAME_SECRET:WEBDAV_PASSWORD_SECRET
삭제
curl -X DELETE https://my-webdav-url/server/database.yml -u WEBDAV_USERNAME_SECRET:WEBDAV_PASSWORD_SECRET

이게 기본적으로 cURL을 이용해 연산하는 방법이다.
그렇다면 이제 개발 환경에서는 처음 제시한 문제들이 해결되었을까?

스프링 프로젝트에 적용

먼저, 개발자들에게 개발 환경 세팅으로 환경 변수를 설정하게 했다.
~/.zshrc에 다음과 같이 두개의 환경 변수를 설정한다.

CREDENTIAL_NAME은 위에서 설정한 username, CREDENTIAL_PW는 password로 하면 된다.

prepare-build.sh 추가

#!/bin/bash
set -e

webdav_url="https://my-webdav-url/server"
resources_path="./src/main/resources"


# 환경 변수 읽기
is_empty_or_null() {
  [ -z "$1" ] || [ "$1" = "null" ]
}

if is_empty_or_null "$CREDENTIAL_NAME" || is_empty_or_null "$CREDENTIAL_PW"; then
  echo "필요한 환경변수(CREDENTIAL_NAME, CREDENTIAL_PW) 중 하나 이상이 설정되어 있지 않거나 null입니다."
  exit 1
fi
download_yml() {
  local file_name=$1
  echo "Downloading ${file_name}"
  curl -Ss -f -X GET "${webdav_url}/${file_name}"  --user "${CREDENTIAL_NAME}:${CREDENTIAL_PW}" -o "${resources_path}/${file_name}" &
}

download_yml "aws-dev.yml"
download_yml "aws-prod.yml"
download_yml "jwt.yml"
download_yml "mysql-dev.yml"
download_yml "mysql-prod.yml"
download_yml "webhook.yml"
download_yml "github.yml"

wait

그 다음, 위와 같은 sh 스크립트를 만들었다.

download_yml이라는 함수를 선언해두고, 호출해가며 yml을 서버에서 동적으로 받아온다.

빌드 이전 무조건 실행되게 하기

저 스크립트는 빌드 또는 실행 이전에 무조건 실행되어야 파일의 최신 상태를 보장한다.
이에 대해 세팅해보자.

먼저, build.gradle에서

tasks.register("preScript", Exec) {
    environment "CREDENTIAL_NAME", System.getenv("CREDENTIAL_NAME")
    environment "CREDENTIAL_PW", System.getenv("CREDENTIAL_PW")

    if (System.getProperty('os.name').toLowerCase().contains('win')) {
        // For windows
        commandLine 'C:\\Program Files\\Git\\bin\\bash.exe', '-c', './prepare-build.sh'
    } else {
        commandLine "sh", "prepare-build.sh"
    }
}

tasks.named("processResources") {
    dependsOn("preScript")
}

tasks.named("bootRun"){
    dependsOn("preScript")
}

tasks.named("build") {
    dependsOn("preScript")

}

tasks.named('test') {
    useJUnitPlatform()
    dependsOn("preScript")
}

위처럼 태스크를 등록해준다. 우리 서버 개발자중에 윈도우 환경이 있어서, git bash로 실행되도록 라인이 추가되어 있다.

다만 IntelliJ를 쓴다면, gradle을 거쳐 실행하지 않는다.
따라서 추가로 세팅해줘야 한다.

IntelliJ 세팅


"구성 편집"을 선택한 뒤


1. 프로젝트 파일로 저장을 체크한다. 이 실행 구성을 git으로 버전관리해, 모든 개발자가 공유할 수 있도록 하는 설정이다.
2. Gradle 작업 실행을 선택한다.


그리고 작업에서 위에서 만든 preScript를 선택해주면 완료된다.

문제가 해결되었을까?

  1. 메신저로 파일을 보내지 않고, 단순히 수정한 사람이 curl을 통해 webdav에서 업데이트 해주면 된다. 그러면 변경 사항이 자동으로 빌드시에 적용된다.
  2. 새 파일이 추가되면, webdav에 올리고 prepare-build.sh에 한 줄 추가해주면 된다. 이 prepare 스크립트는 git으로 버전관리가 되기에, 커밋 버전에 맞게 받을지 말지 정해진다.
  3. github actions에서도 yml을 모두 들고있을 필요 없이, CREDENTIAL_NAME과 CREDENTIAL_PW만 secrets에 설정해주면 된다.
  4. 개발 환경이 이전되더라도, ID와 PW만 알면 바로 작업을 진행할 수 있다.

이를 통해 더이상 카톡으로 하나하나 민감 파일을 공유하지 않을 수 있게 되었다 :)

0개의 댓글

관련 채용 정보