DevOps

AWS Secrets Manager로 애플리케이션에서 RDS 자격증명 정보 보안하기

southouse 2021. 8. 6. 16:14
728x90

보통 AWS를 처음 시작하게 되면 EC2와 관련된 컴퓨팅 리소스를 많이 사용하게 되고, 그 다음으로는 RDS인 것 같다. 그리고 개발자들은 소스 코드의 설정 파일에 RDS 접속 정보를 넣어서 연결하게 된다.

 

이 때, 생길 수 있는 문제는 바로 RDS의 자격증명 정보(마스터 계정 아이디, 비밀번호)가 여과없이 소스 코드에 드러나게 되는 것이다.

 

이 부분을 해결하기 위해 AWS는 Secrets Manager라는 서비스를 출시했다.


AWS Secrets Manager 란?

AWS Secrets Manager는 애플리케이션, 서비스, IT 리소스에 액세스할 때 필요한 보안 정보를 보호하는 데 도움이 됩니다. 이 서비스를 사용하면 수명 주기에 걸쳐 데이터베이스 자격 증명, API 키 및 다른 보안 정보를 손쉽게 교체, 관리 및 검색할 수 있습니다.

 

이 서비스를 활용하여 RDS뿐만 아니라, 온프레미스 환경에 있는 데이터베이스에 대한 자격증명도 안전하게 보관하고 수명 주기를 설정하여 자동으로 교체가 가능하게 되는데, 이번 포스팅에서는 AWS 환경에 있는 RDS의 자격증명에 대해서 Secrets Manager 서비스를 이용하여 소스 코드상에서 노출되지 않도록 설정해보려고 한다. 참고로, 수명주기를 설정하여 교체 관리하는 부분에 대해서는 다루지 않으려고 한다.


들어가기 전에

실습에 필요한 리소스와 환경은 다음과 같고, VPC 환경이 구성되었다는 것을 전제로 한다.

- RDS (MySQL 혹은 PostgreSQL) → 참고로, 필자는 MySQL 8.0.23 버전을 사용했다!

- Secrets Manager

- Spring boot 2.5.3 + Gradle 7.1.1 With IntelliJ

- IAM

- AWS CLI


RDS 생성하기

일단, RDS를 생성하고 기존의 방식대로 소스 코드에 자격증명 정보를 넣은 상태로 접속 테스트만 해보려고 한다.

실습만을 위해서라면, 과금 폭탄을 방지하기 위해 무조건! 프리 티어로 선택하자.
아주 일반적인 RDS 설정이다. 자신이 원하는 대로 설정하도록 하자.
실습의 편의성을 위해 '퍼블릭 액세스' 를 허용하도록 한다. (아주 일반적인 인프라 구성이라면, 사실 퍼블릭 액세스를 허용하지 않는 게 정상이다.)

꼭 설정해주어야 하는 건 프리티어 템플릿 구성, 퍼블릭 액세스 허용, 적절한 보안 그룹 선택이다.

 

생성 시간을 기다리고 나면, 다음과 같이 RDS에 연결할 수 있는 정보를 확인할 수 있다.

우리가 이용할 건 엔드포인트와 포트이다.


RDS 연결하기

이제 위에서 생성한 RDS를 연결을 하기 위해 Spring Boot 프로젝트를 생성해보도록 하자.

Java 11 버전과 Gradle을 사용하였다.
SQL > JDBC API 와 MySQL Driver만 선택해주면 된다. (RDS를 MySQL이 아닌 다른 플랫폼으로 생성했다면, 다른 플랫폼 Driver를 추가하면 된다.)

만약, Gradle이 아니거나, 이미 만들어진 프로젝트라면 따로 Maven Repository에 있는 Dependency를 추가해주면 된다.

 

이후에, 소스코드를 아래와 같이 수정하도록 하자.

src/main/resources/application.properties

spring.datasource.url=jdbc:mysql://secrets-manager-test.c4oexdk2vucc.ap-northeast-2.rds.amazonaws.com
spring.datasource.username=southouse
spring.datasource.password=Passw0rd

src/main/java/com/tistory/southouse/jdbcdemo/JdbcDemoApplication.java

package com.tistory.southouse.jdbcdemo;

import ... // 생략

@SpringBootApplication
@EnableScheduling
public class JdbcDemoApplication {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public static void main(String[] args) { SpringApplication.run(JdbcDemoApplication.class, args); }

    @Scheduled(fixedDelay = 1000L)
    public void foo() {
        System.out.println(jdbcTemplate.queryForObject("select 1", String.class));
    }

}

코드는 간단하다. 스케줄러와 JdbcTemplate을 이용하여 1초마다 'select 1' 이라는 쿼리를 계속 날려주는 코드이다.

RDS 연결과 쿼리 실행에 성공한 모습이다.

여기서 에러가 발생한다면, 아래와 같은 상황을 고려해볼 수 있다.

1. 퍼블릭 액세스가 허용되지 않음.
2. 보안 그룹 설정이 로컬호스트에서 연결을 허용하지 않음.
3. 소스코드에 작성한 RDS의 호스트 URL 혹은 자격증명 정보가 일치하지 않음.

여기까지가 가장 일반적이면서, 간단하게 애플리케이션 환경에서 RDS를 접근하는 방법이었다.


AWS Secrets Manager 설정하기

RDS의 사용자 이름과 암호를 입력하고 RDS를 선택한다.
보안 암호 이름과 설명을 작성한다.
암호를 수명 주기에 따라 자동 교체하는 구성을 설정하는 것인데, 위에서 설명했듯이 교체 부분은 넘어가도록 한다.

이후에 검토 화면에서 검토하고 넘어가주면 된다.

 

정상적으로 설정했다면, 이런 화면을 확인할 수 있다.


AWS Secrets Manager 로 설정된 자격 증명으로 RDS 연결하기

RDS를 연결하기 위해선, Secrets Manager용 jdbc 커넥터 dependency가 필요하다. Maven Repository에서 'aws-secretsmanager-jdbc' 를 검색하여 아래와 같이 추가해주자.

build.gradle

implementation 'com.amazonaws.secretsmanager:aws-secretsmanager-jdbc:1.0.6'

그리고, 위에서 설정한 RDS 자격 증명 정보를 바꿔야 한다.

src/main/resources/application.properties

spring.datasource.url=jdbc-secretsmanager:mysql://secrets-manager-test.c4oexdk2vucc.ap-northeast-2.rds.amazonaws.com
spring.datasource.driver-class-name=com.amazonaws.secretsmanager.sql.AWSSecretsManagerMySQLDriver
spring.datasource.username=dev/secrets-manager-rds/mysql

이제 애플리케이션을 실행하게 되면, 당연하게도 안된다. 왜냐하면 현재 계정에 설정된 자격 증명 정보를 받아올 수 없기 때문이다. 로컬 PC는 설정된 username에 어떤 자격 증명이 설정된지 알 턱이 없다. 따라서 실행하게 되면 다음과 같은 에러를 발생시킨다.

com.amazonaws.services.secretsmanager.model.AWSSecretsManagerException: The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details. (Service: AWSSecretsManager; Status Code: 400; Error Code: InvalidSignatureException; Request ID: b29c0482-c1cf-4b54-a81a-85c864cd7f52)

그래서, IAM 사용자를 생성하여 해당 사용자에게 Secrets Manager의 자격 증명 정보를 가져올 수 있도록 설정해줄 것이다.


IAM 설정하기

IAM 관리 화면에서 사용자를 추가해주도록 한다.

프로그래밍 방식 액세스로 사용자를 추가하도록 한다.
기존 정책에서 'SecretsManagerReadWrite' 를 찾아 권한을 추가해준다.
만약에, IAM 키를 분실했다면, 해당 사용자 선택 후 보안 자격 증명 탭에서 액세스 키를 새로 발급 받으면 된다.

그리고, 로컬 터미널 환경에서 aws-cli를 이용해 위에서 만든 IAM 사용자의 액세스 키와 시크릿 키를 등록해준다.

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

aws-cli가 설치되어 있지 않다면, 아래의 링크를 참고하여 설치하면 된다.

https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html

 

Installing, updating, and uninstalling the AWS CLI - AWS Command Line Interface

Thanks for letting us know this page needs work. We're sorry we let you down. If you've got a moment, please tell us how we can make the documentation better.

docs.aws.amazon.com


다시, AWS Secrets Manager 로 설정된 자격 증명으로 RDS 연결하기

설정은 위에서 다 해뒀으니, 다시 애플리케이션만 실행시켜보도록 하자.

AWS Secrets Manager로 설정한 자격 증명으로 RDS 연결에 성공한 것을 확인할 수 있다.

 

이와 같이, 애플리케이션에서 RDS를 연결할 때 소스 코드내에 자격 증명 정보를 숨김으로써 보안 수준을 향상시킬 수 있었다.

300x250