문제
docker와 ecs를 통해서 배포된 Service에서 AWS SQS나 각종 AWS를 서비스 등을 사용하기 위해서 해당 서비스 프로퍼티에 access-key와 secret-key를 설정해줘야 했습니다. access-key 뿐만 아니라 db에서 사용하는 password들도 소스에 포함되지 않고 외부 설정으로 넘겨줄 방법이 필요하게 되었습니다.
해결
- .properties에서는 환경 변수로 설정
- active profile을 적용하여 properties의 local과 production을 구분
- 환경변수는 Aws Secrets Manger와 CDK설정을 통해서 외부에서 주입
문제를 해결하기 위해서 위의 3가지를 목표로 하고 작업을 시작했습니다. secrets manger를 사용하게 되면 키를 보관함에 따른 비용이 있지만 보안 및 유지보수성을 생각하면 괜찮다고 생각하여 사용하기로 결심했습니다.
CDK Source는 아래와 같이 작업하였습니다. 코드기반으로 인프라 작성을 하면 aws console에서 작업할 필요 없이 간단하게 적용이 가능합니다.
- IAM 생성
- SQS 및 필요한 권한 할당
- Secrets Manger에 key 생성
- 일반 환경 변수와 비밀 환경변수 구분하여서 container에 환경변수로 주입
//create user
const user = new iam.User(this, 'user', {
userName: betaConfig.serviceName + "_IAM"
});
//sqs 권한 할당
user.addManagedPolicy(ManagedPolicy.fromAwsManagedPolicyName('AmazonSQSFullAccess'));
user.addManagedPolicy(ManagedPolicy.fromAwsManagedPolicyName('AmazonSQSReadOnlyAccess'));
//key 생성
const accessKey = new iam.AccessKey(this, 'AccessKey', { user });
const IamSecret = new secretsmanager.Secret(this, 'Secret', {
secretName: betaConfig.serviceName + "_secretKey",
secretStringValue: accessKey.secretAccessKey,
});
//보안 환경 변수
const secretEnv = {
DATABASE_USERNAME: Secret.fromSecretsManager(rdsInsatnce.db.secret, "username"),
DATABASE_PASSWORD: Secret.fromSecretsManager(rdsInsatnce.db.secret, "password"),
DATABASE_HOST: Secret.fromSecretsManager(rdsInsatnce.db.secret, "host"),
DATABASE_NAME: Secret.fromSecretsManager(rdsInsatnce.db.secret, "dbname"),
DATABASE_PORT: Secret.fromSecretsManager(rdsInsatnce.db.secret, "port"),
SECRET_KEY: Secret.fromSecretsManager(IamSecret),
};
//일반 환경 변수
const normalEnv = {
ACCESS_KEY: accessKey.accessKeyId,
LOGISTICS_SQS_NAME: LOGISTICS_SQS_NAME,
ENDPOINT_CUSTOMER: dns[SERVICE.CUSTOMER],
ENDPOINT_SELLER : dns[SERVICE.SELLER ],
};
//기타 소스 생략
//task definition에 컨테이너 추가
taskDefinition.addContainer(`container`, {
containerName: `${props.serviceName}-container`,
image: ecs.ContainerImage.fromEcrRepository(ecrRepo, 'latest'),
memoryLimitMiB: 256,
secrets: props.containerSecretEnv,
environment: props.containerEnv,
cpu: 256,
logging: ecs.LogDrivers.awsLogs({
streamPrefix: "prod",
logGroup: logGroup,
}),
portMappings:[
{hostPort:80, containerPort: props.containerPort, protocol: ecs.Protocol.TCP},
]
})
.properties파일을 아래와 같이 설정을 진행하였습니다.
spring.datasource.url=jdbc:postgresql://${DATABASE_HOST}:${DATABASE_PORT}/${DATABASE_NAME}
spring.datasource.username=${DATABASE_USERNAME}
spring.datasource.password=${DATABASE_PASSWORD}
spring.datasource.driver-class-name= org.postgresql.Driver
app.sqs-queue-name=${LOGISTICS_SQS_NAME}
cloud.aws.credentials.instance-profile=false
cloud.aws.credentials.access-key=${ACCESS_KEY}
cloud.aws.credentials.secret-key=${SECRET_KEY}
'사이드프로젝트 > chan' 카테고리의 다른 글
VPC Endpoint 를 사용하여 private하게 Infra 개선하기 (0) | 2022.09.16 |
---|---|
[infra] MSA구성에 따른 인증 / 인가 로직 구현 (0) | 2022.09.02 |
[service]여러 서비스 사용에 따른 Integration Test (0) | 2022.09.02 |
[service] 라이더 할당시 동시에 할당되는 문제 해결 (0) | 2022.09.02 |
[service] 물류서비스 매칭 진행시 동시성 문제 해결 (0) | 2022.09.02 |