본문 바로가기
  • 오늘도 한걸음. 수고많았어요.^^
  • 조금씩 꾸준히 오래 가자.ㅎ
IT기술/클라우드, VM, AWS

[AWS] SpringBoot 시크릿 매니저 사용하기.

by 미노드 2024. 3. 3.

스프링 부트에서 프로퍼티 정보를 SecretManager를 활용해서 불러오는 식으로 변경 해봤습니다.
보안적인 이슈를 막기 위해서, 단단한 프로젝트를 만들려면, 프로퍼티에 있는 db정보를 암호화 하는 것도 필요합니다.

그것을 위한 방법으로 KMS나 SecretManager를 통해 외부에서 암호정보를 가져오는 전략이 있는데,
이를 프로젝트에 적용해봤습니다.

필요한 것은 Secret Manager와 스프링 부트 프로젝트 입니다.
Secret Manager를 만들고, 거기에 db의 ID와 PW 정보를 보관하고, 부트 프로젝트 실행시 시크릿 매니저에서 값을 가져와 적용시키는 방식으로 개발했습니다.

- 시크릿 매니저 준비

저는 자유로운 형식의 키보관 목적이기에  "다른 유형의 보안 암호"를 선택했습니다.

보안 암호 이름을 적습니다.

시크릿매니저에서 지원하는 보안 암호를 자동으로 교체할 수 있는 기능입니다.
람다의 지원이 필요합니다.

시크릿 매니저의 키를 불러올 수 있는 예제 소스코드 입니다.

시크릿 매니저가 만들어 졌습니다.

여기까지 시크릿매니저를 만드는 부분이며, 추가적인 작업이 필요합니다.

- 리소스 권한 설정 (IAM 권한 필요 SecretManagerReadWrite)
- IAM 권한을 가진 IAM USER의 액세스 키 만들기
- 서버에 AWS secretManager 설정하기

1. 리소스 권한 설정 (IAM 권한 필요 SecretManagerReadWrite)

IAM에서 사용자를 생성합니다.(기존사용자 써도 됨니다.)
secretManagerUser

사용자 눌러서 권한 추가를 누릅니다.

권한추가 눌러서 SecretManagerReadWrite 를 추가합니다.

추가된게 확인됩니다.

2. 권한 추가된 사용자에 액세스 키 만들기

액세스키 모범사례는 로컬코드로 선택했습니다. 원하는데로 선택해도 됩니다.

태그도 간단히 적었습니다.
구분을 위해 용도에 맞춰 작성합니다.

생성하면 액세스 키/ 비밀 액세스 키가 발급됩니다.

3. 서버에 AWS secretManager 설정하기

서버에 터미널을 띄우고 aws config 를 실행합니다.

 

아래 4개 정보를 입력하면 됩니다. 시크릿 매니저 권한을 가진 IAM 유저의 액세스 키, 비밀 액세스 키, 시크릿 매니저 리전 네임, format 을 입력합니다.

AWS Access Key ID [None]: 
AWS Secret Access Key [None]:
Default region name [None]: 
Default output format [None]: json

이제 aws메서드로 secret매니저가 조회 되는지 확인 해보겠습니다.

aws secretsmanager help 를 통해 도움말을 볼 수 있습니다.

aws secretsmanager describe-secret --secret-id ARN주소

이런식으로 Arn에 맞춰 원하는 시크릿매니저 정보 조회가 가능합니다.

aws secretsmanager get-secret-value --secret-id ARN 주소 

이 명령어로 시크릿 매니저의 값을 조회할 수 있습니다.
SecretString 영역이 값이저장된 부분입니다.
key:Value 형식으로 저장된 것이 확인됩니다.

aws secretsmanager list-secrets

현재 설정된 액세스키로 조회가능한 시크릿을 확인할 수 있습니다.
시크릿 매니저에 그룹이나 권한 설정으로 사용자마다 접근 가능하도록 설정하면 됩니다.

 

시크릿매니저는 설정완료되었고, 이제 프로젝트에서 불러오겠습니다.
Gradle 환경의 스프링 부트 기반 프로젝트로 다음의 의존성을 추가합니다.

implementation 'com.amazonaws:aws-java-sdk-secretsmanager:1.12.619'

저는 sdk를 이용하여 secretManager를 불러오는 기능을 추가했는데,
db의 계정정보를 불러오는 것이 목적입니다.
계정 정보를 통해 dataSource가 자동으로 만들어 지는데, 자동으로 만들어지기 전에 secretManager의 정보를 불러와야 합니다.

그러기 위해 addInitializers를 추가하여 스프링 실행시 프로퍼티에 값을 먼저 추가하는 방식으로 구현했습니다.
addInitializer를 추가하여 실행하면 프로퍼티에 secretManager정보를 먼저 추가 가능합니다.
이를 위해 CustomApplicationContextInitializer를 별도로 구현했습니다.

import com.amazonaws.services.secretsmanager.AWSSecretsManager;
import com.amazonaws.services.secretsmanager.AWSSecretsManagerClientBuilder;
import com.amazonaws.services.secretsmanager.model.GetSecretValueRequest;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;

import java.io.IOException;
import java.util.Map;

// 스프링부트 실행 하면서 추가하기

public class CustomApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        ConfigurableEnvironment environment = applicationContext.getEnvironment();

        try {
            // 시크릿매니저 불러오기
            AWSSecretsManager secretsManager = AWSSecretsManagerClientBuilder.defaultClient();
            GetSecretValueRequest getSecretValueRequest = new GetSecretValueRequest().withSecretId(arn0);
            String secretString = secretsManager.getSecretValue(getSecretValueRequest).getSecretString();

            Map<String, String> secretMap;
            secretMap = new ObjectMapper().readValue(secretString, new TypeReference<>() {});
                for (String key : secretMap.keySet()) {

                    String value = secretMap.get(key);
                    System.setProperty(key, value); // 값 프로퍼티에 추가.
                }

        } catch (IOException e) {
            // 예외 처리
        }
    }
}

프로퍼티엔 미리 시크릿매니저를 읽기 위한 arn을 추가했습니다.

이제 실행 후 여기 값들이 잘 읽어지는지 확인해봐야 합니다.

Application.properties 추가

datasource에 시큐리티 매니저에 있는 minod_id, minod_pw를 주입받을 수 있도록 프로퍼티 정보를 변경했습니다.
결과를 보면 문제없이 Hikari Pool 이 만들어 지는것을 확인했습니다.
값이 잘 불러와지는 것 같습니다.

비교를 위해 프로퍼티 값을 일부러 틀려 보겠습니다.
예상대로 로그인 실패가 일어납니다.
정확한 암호 값을 시크릿매니저에서 읽어왔기에 이것이 가능한 것을 확인할 수 있습니다.

시크릿매니저 활용하는 부분을 정리 해봤습니다.

'IT기술 > 클라우드, VM, AWS' 카테고리의 다른 글

AWS 기초, 용어정리(5)  (0) 2023.10.16
AWS 기초, 용어정리(4)  (0) 2023.10.12
AWS 기초, 용어정리(3)  (0) 2023.10.11
AWS 기초, 용어정리(2)  (0) 2023.10.11
AWS 기초, 용어정리(1)  (0) 2023.10.10