기존 백엔드에 보안 정보들을 저장할때는 그냥 저장할 수는 없기때문에 해당 보안 정보를 암호화를 하거나, 환경 변수에 넣곤한다.
하지만 이렇게 사용할경우, 애플리케이션 내부 복잡도가 높아지고 중앙관리가 힘들어진다는 단점이 존재한다
현재 프로젝트를 보게되면 jasypt 암호화를 하여 저장하고, 어떤 값들은 환경변수로 저장하기때문에 관리에 불편함이 따른다.
이를위해 나온게 Secrets Manager로 보안 암호를 생성하고 같은 리전내에 있다면 간단하고 안전하게 보안 정보들을 사용할 수 있다.
키와 값을 테스트로 저장하기 위해 여러 형식을 저장할 수 있는 “다른 유형의 보안 암호”를 선택 후, db_id, db_pw에 대한 키와 값을 넣었다

그리고 암호화 방식은 기본 SecretsManager의 KMS를 사용하였다
애플리케이션에서 해당 보안 암호를 찾기 위한 보안 암호 이름을 다음과 같이 설정해주었다
PW같은 경우를 Lambda와 연계하여 주기적으로 자동으로 교체해주는 선택지가 있지만 지금은 그러지 않기때문에 스킵하였다.
https://mvnrepository.com/artifact/io.awspring.cloud/spring-cloud-aws-starter-secrets-manager
테스트 Application 설정 적용
spring.config.import=aws-secretsmanager:gist/test/db
spring.cloud.aws.credentials.access-key=${secretsmanager.access-key}
spring.cloud.aws.credentials.secret-key=${secretsmanager.secret-key}
설정은 꽤 간단한데, 먼저 의존성을 추가시켜주고
application.properties 혹은 yml에 위와같이 import를 시켜주어야한다. 이때, aws-secretsmanager:뒤에 보안 암호를 넣으면 되고, 추가로 보안 암호를 여러개 넣고싶을경우 ; 세미콜론으로 구분하면된다.
아래의 access-key와 secret-key는 프로덕션 환경에서는 IAM권한으로 인해 필요가 없지만, 로컬 환경에서는 테스트를 위해 필요하기때문에 로컬 환경변수로 넣어두었다
@Component
public class SecretsManagerTestConfig {
@Value("${db_id}")
private String id;
@Value("${db_pw}")
private String pw;
@PostConstruct
public void init() {
System.out.println("id: " + id);
System.out.println("pw: " + pw);
}
}
간단한 확인을 위해 위와같이 값을 불러온다은 Spring boot 애플리케이션이 시작되면 바로 확인할 수 있게 코드를 작성해보았다.
그리고 결과를 보면

위와 같이 작성했던 값이 잘 들어오는 모습을 보여준다.
보안 정보에 대한 보안 암호를 생성하였다
해당 보안 암호는 아래와 같은 JSON 형식으로 저장된다.
{
"encryption_key": "file-encryption-key",
"db_url": "jdbc:postgresql://test.com:5432/postgres",
"db_name": "test_database",
"db_username": "test",
"db_password": "testpw",
}
IAM에 SecretsManager를 읽을 수 있는 권한을 추가해준다
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue",
"secretsmanager:DescribeSecret"
],
"Resource": "secrets manager arn"
}
]
}
secrets manager의 arn은 해당 보안 암호에 들어가서 arn을 확인해야한다.
arn뒤에 경로와 랜덤 접미사를 붙여주어야한다 (ex: project/dev/backend-aegbsd)
ECS에 TaskRole에 해당 정책을 적용시켜야한다
IAM의 역할에서 사용중인 ECS 역할에 들어간 후 아래와같이 권한 정책에서 SecretsManager 권한을 추가해준다
ECS뿐만아니라 EC2도 EC2에 연결된 역할에 권한을 추가해주면 된다
위에서 설명한거와 같이 의존성을 추가해준뒤, properties에 secrets manager을 import 시켜준다
spring.config.import=aws-secretsmanager:project/dev/backend
그리고 기존 키 값을 secrets manager의 보안 암호 키 값으로 대체를 한다
기존에 설정은 아래와 같았다.
spring.datasource.project-rds.url=ENC(AlawknglwearkbnaeloirfjawECVASDKLjvhawhe1=afalnjkgWEFALKJ)
spring.datasource.project-rds.username=ENC(+zdsafjkl2qASLDF1nhFV=)
spring.datasource.project-rds.password=ENC(falejlawdhgvawsedfjJfe+0=)
spring.datasource.project-rds.driver-class-name=org.postgresql.Driver
jasypt로 암호화가 되어있지만, 해당 암호화 키를 환경변수에 저장을 해야됐고, 이 암호키가 유출되면 모든 정보가 한번에 유출될 수 있는 상태이다.
그리고 보안 암호를 적용시켜보면 아래와 같다
spring.datasource.project-rds.url=${db_url}
spring.datasource.project-rds.username=${db_username}
spring.datasource.project-rds.password=${db_password}
spring.datasource.project-rds.driver-class-name=org.postgresql.Driver
모든 보안 정보들이 키값만 보이게 되기때문에 정보 유출의 위험이 사라지고, 모든 보안 암호가 secrets manger로 모여, 관리가 편해진다.
애플리케이션이 실행되고 spring boot내부 credentials가 없음에도 iam권한으로 보안 암호를 import해서 정상적으로 실행이 되었다

Secrets Manager를 도입하게 된다면 확실히 키 저장에 대한 고민과 관리에 대한 불편함이 줄어들게된다.
또한 Secrets Manager를 사용한다해도 성능에 차이가 없기때문에
애플리케이션 서비스가 AWS 내부에서 동작한다면 Secrets Manager 사용을 추천