DevOps

AWS Parameter Store로 소스 코드 내 중요 설정 값 보안하기

southouse 2022. 7. 29. 12:30
728x90

Spring 코드를 작성하다가 JWT 토큰 혹은 암호화 키 값 등과 같이 코드 내에 중요 설정 값을 하드코딩되어 있는 것을 보고 보안 상 취약할 거 같아 관련 레퍼런스들을 찾아보니, AWS Parameter Store를 통해 키/값을 저장하고 코드 내에서 키를 통해 불러올 수 있는 것을 알아냈다.

 

하지만, 현재 필자는 Spring boot 2.7.0 버전을 사용하고 있는데 2.4.0 버전 이상부터 application 리소스 설정하는 방식이 바뀌어서 기존에 나와 있는 레퍼런스를 그대로 참고해서는 제대로 동작을 안 했다. 그래서 이번 기회에 최신 버전으로 동작하는 코드를 정리해보려고 한다.

 

추가로, 이번 기회에 Spring boot 2.4.0 이전 버전에서 파라미터 스토어를 사용하다가 2.4.0 버전 이상으로 마이그레이션 하는 분들이 보면 도움이 될 것 같다. 이번 2.4.0 버전 이상부터는 .properties 혹은 .yml 파일과 같은 애플리케이션 설정 파일 이름을 커스터마이징하면 불러오지 않는데, 기존 방식에서는 bootstrap.yml 파일에 파라미터 스토어 키/값을 정의하기 때문에 반영이 되지 않는다. 물론 예외로 처리할 수 있는 방식(use-legacy-processing 설정)은 있지만.. 기본적으로 권장하는 방식을 사용하고자 한다.

실습 환경

  • AWS
    • System Manager > Parameter Store
    • IAM
    • CLI
  • java 17 (corretto)
  • Gradle 7.4.1
  • Spring boot 2.7.0

코드 작성

의존성 추가

...

dependencyManagement {
    imports {
        mavenBom "io.awspring.cloud:spring-cloud-aws-dependencies:2.4.2"
    }
}

...

dependencies {
    ...

    // https://mvnrepository.com/artifact/io.awspring.cloud/spring-cloud-starter-aws-parameter-store-config
    implementation group: 'io.awspring.cloud', name: 'spring-cloud-starter-aws-parameter-store-config', version: '2.4.2'

    ...
}

application.yml 설정

spring:
  config:
    activate:
      on-profile: local
    import: 'aws-parameterstore:'
aws:
  paramstore:
    enabled: true
    prefix: /southouse
    name: common-parameter
    profileSeparator: _

참고 사이트 부분에 property 설정에 대한 설명이 있지만, 지금 사용하는 것에 대해서 간략하게 설명하자면,

  • aws.paramstore.enabled = 사용 여부 설정
  • aws.paramstore.prefix = 파라미터 스토어 키 이름 중 가장 앞, 첫번째에 위치
  • aws.paramstore.name = 파라미터 스토어 키 이름 중 두번째에 위치
  • aws.paramstore.profileSeparator = 파라미터 스토어 키 이름 중 name 부분에서 profile 구분자 역할

위의 설정에 따르면 파라미터 스토어의 키 이름은 다음과 같은 구조가 된다.

/southouse/common-parameter_{SPRING_PROFILES_ACTIVE}

 

만약 profile을 local, dev, prod 로 구분한다면,

  • /southouse/common-parameter_local
  • /southouse/common-parameter_dev
  • /southouse/common-parameter_prod

로 구성을 해놓으면 알아서 profile에 따라 해당 파라미터 스토어 값을 찾게 된다.

클래스 생성

@Getter
@NoArgsConstructor
@Configuration
public class ParameterStoreProperties {

    @Value("${jwt.secretkey}")
    private String jwtSecretKey;

}

properties 파일에 설정된 파라미터 스토어 값을 불러오는 클래스이다.

존처럼 properties 값을 불러오는 @Value 어노테이션을 사용하여 불러온다.

 

단, Value 어노테이션 값이 위의 /southouse/common-parameter_{SPRING_PROFILES_ACTIVE}/{VALUE_NAME} 구조 세번째에 위치하는 가장 마지막 값이 된다.

 

따라서, 파라미터 스토어에 다음과 같은 이름을 가진 키를 정의하면 된다.

  • /southouse/common-parameter_local/jwt.secretkey
  • /southouse/common-parameter_dev/jwt.secretkey
  • /southouse/common-parameter_prod/jwt.secretkey

이제 AWS에서 파라미터 스토어 키/값을 설정해보도록 하자.

AWS 설정

파라미터 스토어에 키/값 설정

AWS Systems Manager > 애플리케이션 관리 > 파라미터 스토어 > 파라미터 생성
파라미터 생성 화면

파라미터 이름은 위에 애플리케이션 코드에서 지정한 이름 규칙대로 설정하면 되고, 유형은 중요한 값이기 때문에 보안 문자열을 선택하도록 하자.

 

이제, 애플리케이션에서 실제로 사용을 해보기 위해서는 AWS SSM 파라미터 스토어를 읽을 수 있는 권한을 가진 IAM 액세스 키 발급이 필요하다. 해당 포스팅에서는 IAM 발급에 대해서 자세하게 다루진 않겠다.

IAM 계정 발급

AWS IAM > 액세스 관리 > 사용자 > 사용자 추가

IAM 액세스 키를 사용할 예정이기 때문에, '액세스 키 - 프로그래밍 방식 액세스' 를 체크하여 다음으로 넘어간다.

정책 중 'AmazonSSMReadOnlyAccess' 를 추가

❯ aws configure
AWS Access Key ID [None]: 액세스 키 입력
AWS Secret Access Key [None]: 시크릿 키 입력
Default region name [None]: ap-northeast-2
Default output format [None]: json

생성한 IAM 계정의 액세스 키와 비밀 액세스 키를 aws-cli 를 이용하여 현재 PC에 등록한다.

 

참고로 지금은 IAM 계정을 발급 받아 사용하지만, 나중에 애플리케이션을 EC2 혹은 ECS와 같은 AWS 컴퓨팅 리소스에 배포하게 된다면 보안 상 액세스 키를 발급 받아 사용하기 보단 IAM 역할을 등록하여 사용하는 편이 좋다.

테스트 코드 작성

@ExtendWith(SpringExtension.class)
@ActiveProfiles("local")
@SpringBootTest
public class ParameterStorePropertiesTest {

    @Autowired
    private ParameterStoreProperties properties;

    @Test
    void local_파라미터를_가져온다() throws Exception {
        assertEquals(properties.getJwtSecretKey(), "southouse");
    }

}

마지막으로 다시 코드로 넘어와서, 테스트 코드를 작성하여 테스트 해보면 된다!

테스트 성공

추가로, 파라미터 스토어로 설정하는 파라미터는 동적으로 값이 할당이 안 된다고 한다.

 

예를 들면, 애플리케이션을 실행한 뒤에 파라미터 스토어에서 값을 바꾸게 되더라도 불러오는 값은 예전 값으로 계속 불러온다고 하니까 사용할 때 주의를 해야한다. 자세한 내용은 아래에 나와 있는 참고 사이트 중 향로님 블로그를 참고하면 된다.

참고 사이트

 

Spring Boot에서 AWS 파라미터 스토어로 private 설정값 사용하기

이를 테면 DB의 접속정보나 암호화에 사용될 Salt Key 등은 프로젝트 코드 내부에서 관리하기엔 위험이 따릅니다. 누구나 볼 수 있기 때문이죠. 이건 사내 private 저장소를 사용해도 비슷합니다. 사

jojoldu.tistory.com

 

Spring boot integrating with last version of parameter-store or secrets (sample) · Discussion #12 · awspring/spring-cloud-aws

Hi, I am trying to create a spring boot app integrating with the latest version of "spring-cloud-aws-parameter-store-config (3.0.0-SNAPSHOT)" module. Based on the documentation I have def...

github.com

 

GitHub - spring-attic/spring-cloud-aws: All development has moved to https://github.com/awspring/spring-cloud-aws Integration fo

All development has moved to https://github.com/awspring/spring-cloud-aws Integration for Amazon Web Services APIs with Spring - GitHub - spring-attic/spring-cloud-aws: All development has moved to...

github.com

 

300x250