[NEST] nestjs에서 aws secret-manager 사용하기

김지원·2022년 12월 20일
3

nest

목록 보기
3/4

이 글을 작성하게 된 이유

NEST JS로 이뤄져 있는 서버에서 aws secret manager를 이용해 민감한 환경변수를 사용하려고 구글링을 했는데 관련 내용이 없어 글 쓰게 되었습니다!
바로 들으갑니다~

적용 방법

처음에 사용하기 위해 @aws/sdk 라이브러리를 설치하여 service를 만들어 DI를 진행하려고 했었습니다..

하지만 @aws/sdk의 내용을 스트링으로 모두 가져가다보니 메모리 과다가 되었고 서버를 ec2에 올리자마자 터져 버렸습니다.

이 내용을 디버깅하는 부분은 나중에 작성하도록 하고 이럴 줄 알고 aws에서는 서비스마다 사용할 수 있는 라이브러리를 준비해두었습니다.
(저 같은 사람이.. 많은가봐요 하하)

AWS 문서를 보면 제가 하려는 작업들이 잘 정리되어 적혀있는 것을 볼 수 있습니다.

하지만 제가 알고 싶은 aws secret manger 안에 있는 값을 꺼내 오는 부분이 없었습니다..ㅠㅠㅠ

이제 진짜 코드를 까볼까요
사쿠라여

aws-secrets-manger/aws-secrets-manger.service.ts

import {
  GetSecretValueCommand,
  SecretsManagerClient,
} from '@aws-sdk/client-secrets-manager';
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';

@Injectable()
export class AwsSecretsManagerService {
  constructor(private readonly configService: ConfigService<EnvVars, true>) {}

  async getSecretValue(key: string) {
    const secretManager = new SecretsManagerClient({
      region: this.configService.get('AWS_SECRET_REGION', { infer: true }),
    });

    const command = new GetSecretValueCommand({
      SecretId: this.configService.get('AWS_SECRET_NAME', {
        infer: true,
      }),
    });

    try {
      const secretResult = await secretManager.send(command);
      const secretList = JSON.parse(secretResult.SecretString);
      return secretList[key];
    } catch (error) {
      throw new HttpException(
        'internalError',
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }
}

첫번째로 라이브러리 중 @aws-sdk/client-secrets-manger를 설치해줍니다.

그리고 공유드렸던 위 문서와 같이 자신이 사용하는 지역에서 시크릿 매니저 클라이언트를 생성한 후

라이브러리의 GetSecretValueCommand함수를 이용해 스크릿 아이디에 만들어 두었던 시크릿 매니저의 이름을 넣어주어 aws에 전송할 명령어를 만들어줍니다.

이렇게 하면 사용할 준비는 끝났습니다!

그리고 자신이 만들어둔 시크릿 매니저의 암호화 키에 있는 내용을 모두 가져올 수 있는 SecretString 명령어를 사용해줍니다.

SecretString 명령어는 이름과 같이 JSON 형식이 아닌 string 형식으로 나오기 떄문에 JSON으로 파싱을 한번 해준 후 자신이 원하는 값의 키값을 적어주면 원하는 값이 나오게 됩니다.

저는 원하는 key값을 넣어 value 값을 받아오는 함수를 만들어 사용했습니다.

그리고 이 service를 다른 클래스에서도 사용할 수 있게 exports를 해주어야합니다.

aws-secrets-manger/aws-secret-manger.module.ts

import { Module } from '@nestjs/common';
import { AwsSecretsManagerService } from './aws-secrets-manager.service';
import { ConfigService } from '@nestjs/config';

@Module({
  providers: [AwsSecretsManagerService, ConfigService],
  exports: [AwsSecretsManagerService],
})
export class AwsSecretsManagerModule {}

실제 사용 내용

export const typeOrmConfig: TypeOrmModuleAsyncOptions = {
	imports: [ConfigMoudle, AwsSecretsMangerModule], 
    inject: [ConfigService, AwsSecretsMangerService],
    useFactory: async (
    	configService: ConfigService<EnvVars, true>,
        awsSecretsManger: AwsSecretsMangerService,
    ) => {
    	let password = configService.get('DB_PASSWORD', { infer: true });
        if (nodeEnv === 'production') {
        	password = await awsSecretsManager.getSecretValue('DB_PASSWORD');
        }
        ...
    }
}

이런 식으로 사용하게 된다!

SecretString 명령어는 공식 문서에 나와 있지 않아 이 글을 쓰게 되었고.. 나중에 유용하게 쓰길 바라면서.... 적어보는걸로 이 글은 끝내보도록 하겠습니다ㅎㅎ

특정 값만 꺼내올 수 있는 명령어가 있다면 댓글로 공유 한번 부탁드립니다~

profile
backend-developer

0개의 댓글