티스토리 뷰
AWS Secrets Manager를 사용하게 된 계기
현재 진행 중인 프로젝트에서 커밋 한 코드를 깃헙에 PR 올렸을 때 발생하는 CI(Continuous Integration) 문제 해결법에 대해서 알아보겠다.
우리 프로젝트의 경우 PR에 올라간 커밋한 내용들에 빌드가 정상적으로 수행되는지 GitHub Actions에서 검사한다. 분명 로컬에서 작업했을 때 빌드에 문제도 없었고, 테스트 코드 또한 정상적으로 모두 수행되었다. 그래서 당연히 PR 올렸을 때도 문제가 없을 줄 알았다.
그러나 아래를 보면 X 표시가 보일 것이다. X의 의미는 내가 올린 코드가 빌드에 문제가 생겼다는 의미이다.
왜 문제가 발생했을까? 이유는 간단하다. .gitignore에 추가된 파일이 깃헙에 올라가지 않기 때문이다. GitHub Actions 입장에서는 해당 파일이 없기 때문에 빌드에서 문제가 발생하는 것이다. 아래 application.yml에 작성한 내용 중에 profiles 속성이 있다. AWS S3 설정 정보를 application-aws.yml에 작성하고 application.yml에서 참조할 수 있도록 하였다. 그러나 application-aws.yml의 경우. gitignore에 의해 깃헙에 올라가지 않기 때문에 당연히 빌드 문제가 발생할 수밖에 없다.
이러한 문제를 해결하기 위해서 여러가지 방안이 나왔다.
- AWS Secrets Manager
- Github Secrets
- Submodules
- Jasypt
많은 선택지가 있지만 우리 프로젝트는 AWS Secrets Manager를 선택하였다. 각각의 장단점이 있고 좋고 나쁨을 판단할 수가 없었다.
우리는 AWS Secrets Manager와 Github Secrets로 선택지를 줄였고, 뭐가 좋을지 고민을 했다. 둘 다 설정 값을 직접 등록해야는 특징이 있다. 그러나 AWS를 사용하는 1개의 Secrets Manager를 생성해도 여러 Repo에서 사용할 수 있다는 장점이 있어 우리 프로젝트에서는 AWS Secrets Manager를 채택했다.
AWS Secrets Manager 생성하기
SpringBoot에서 yml 등에서 사용되는 설정 값을 AWS Secrets Manager를 통해 관리해보도록 하겠다.
먼저 AWS 콘솔에서 Secrets Manager 콘솔을 들어간다.
AWS RDS를 사용하지 않고, 로컬에 있는 MySQL을 사용할 것이기 때문에 다른 유형의 보안 암호를 선택한다.
yml 등에서 사용할 환경변수 key와 value를 입력한다. (추후에 추가할 수 있다.)
보안 암호를 입력하면 되는데, 주의할 점이 있다. 보안 암호 이름의 경우 /secret/가 prefix로 붙기 때문에 /secret/** 형식으로 작성해야 한다. 다른 prefix를 사용할 경우 SpringBoot에서 별도로 수정하는 과정이 필요하다.(물론 간단하다)
위에서 다루지 않은 부분은 별도로 작성할 필요가 없다는 것이다. 최종적으로 아래와 같이 보안 암호가 생성된다.
AWS IAM 권한 부여하기
위에서 등록한 보안 암호를 사용하기 위해서는 IAM에 SecretsManagerReadWrite 권한이 필요하다. IAM에 해당 권한을 부여한다.
AWS Credential 지정
애플리케이션에서 AWS에 직접 접근할 수 있도록 Credential을 지정한다. 반드시 해당 Credential에 SecretsManagerReadWrite 권한이 있어야 한다.
SpringBoot에서 AWS Secrets Manager 사용하기
먼저 build.gradle에 의존성을 추가한다.
참고로 SpringBoot v3.2.4를 기준으로 작성한 게시물이다.
implementation 'org.springframework.cloud:spring-cloud-starter-bootstrap:3.0.3'
implementation 'org.springframework.cloud:spring-cloud-starter-aws-secrets-manager-config:2.2.6.RELEASE'
다음으로 bootstrap.yml를 프로젝트 최상단에 생성 후, 내용을 작성한다.
aws:
secretsmanager:
# prefix: /secret/ # prefix의 기본 값이 /secret/이다. prefix를 지정하지 않으면 /secret/로 설정된다.
name: past-forward
cloud:
aws:
region:
static: ap-northeast-2
마지막으로 AWS Secrets Manager에 등록된 key에 정상적으로 접근이 되는지 확인한다.
@RestController
@RequestMapping("/aws-secrets")
public class AWSCheckController {
@Value("${hope_dev}")
public String secretKey;
@GetMapping
public String healthCheck() {
return "AWS Secrets Key : " + secretKey;
}
}
key에 대한 value가 정상적으로 출력된다.
참고로 AWS Secrets Manager에 key값이 없는 상태에서 Application을 실행하면 오류가 발생합니다. Application에서 @Value 애너테이션으로 AWS Secrets Manager에 등록된 hope_dev 키에 접근하려고 시도하지만, 해당 키가 등록되어 있지 않기 때문에 Injection 오류가 발생합니다.