Nestjs + SecretManager

김동현·2023년 12월 28일
0

Nestjs

목록 보기
2/6
post-thumbnail

💡 Secret Manager

  • 현재 .env 파일에서 환경 변수를 관리하고 있었다.
    • 대부분 어플리케이션은 외부에 노출돼서는 안되는 비밀값을 갖고 있다!
      (ex. 데이터베이스 접속정보, 서드파티 서비스 호출을 위한 액세스 키 등)
  • AWS SecretManager를 도입하여 비밀 값을 AWS에서 관리해보자.

npm: dotenv
AWS Secrets Manager이란 무엇인가요? - AWS Secrets Manager

💡 AWS_REGION, AWS_SECRET_NAME 설정

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

@Injectable()
export class SecretsManagerService {
    async getSecretValue(key?: string) {
        const secretManager = new SecretsManagerClient({
            region: process.env.AWS_REGION,
        });

        const command = new GetSecretValueCommand({
            SecretId: process.env.AWS_SECRET_NAME,
        });

        try {
            const secretResult = await secretManager.send(command);
            const secretList = JSON.parse(secretResult.SecretString);
            return key ? secretList[key] : secretList;
        } catch (error) {
            throw new HttpException('internalError', HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }
}
  1. AWS의 리전시크릿 매니저 이름을 알고 있어야 시크릿 매니저 값을 불러올 수 있으므로 전역에 두 환경 변수를 서버의 전역에 설정해준다.
  • 영구적으로 전역 변수 설정하는 방법
  1. ~/.bashrc ~ 경로에 .bashrc 파일을 생성한다.
  2. KEY=VALUE 형태로 저장할 환경 변수 값을 저장한다.

💡 AWS_SECRET_MANAGER 사용하기

import { DynamicModule, Module } from '@nestjs/common';
import { SecretsManagerService } from './secret-manager.service';

@Module({
    providers: [SecretsManagerService],
    exports: [SecretsManagerService],
})
export class SecretManagerModule {
    static forRoot(): DynamicModule {
        return {
            global: true,
            module: SecretManagerModule,
        };
    }
}
  • 해당 SecretManagerModule을 글로벌로 사용할 수 있도록 설정한 후 SecretManagerService를 생성자 주입해서 사용한다.
import { Controller, Get } from '@nestjs/common';
import { SecretsManagerService } from 'SRC/configs/secret-manager/secret-manager.service';

@Controller()
export class AppController {
    constructor(private readonly awsSecretsManger: SecretsManagerService) {}

	@Get('/')
    check() {
        return this.awsSecretsManger.getSecretValue('DB_PORT');
    }
}
{
    "statusCode": 200,
    "result": "3306"
}
  • SecretManager 내의 해당 값을 사용 할 수 있게 된다!

🤔 SecretManager는 자격 증명을 어디서 얻어올까?

SecretManager를 구현하면서 필요한 값은 AWS 리전과, SecretManagerName 이었다.
그럼, ACCESS KEY와 SECRET KEY는 어떻게 알고 가져가는 걸까?
전역에 설정되어 있는 AWS_ACCESS_KEY_ID 환경변수를 유효하지 않은 값으로 변경해 보았다.

🤯 그 때 아래와 같은 에러가 발생했다!!

아래의 StackOverFlow에서 힌트를 얻었다.
Stack Over Flow: Where does AWS Secrets Manager get AWS Credentials?

위 이미지를 보면 답변에 Java 언어를 기준으로 AWS_SDK는 첫번째로 환경 변수를 확인한다고 하였다.
Java 언어 AWS-SDK

그럼 🤔 JavaScript는?

JavaScript AWS-SDK를 보면 동일하게 환경 변수에서 찾는 다는 것을 알 수 있었다.

즉, 전역 환경 변수에 유효한 AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY를 추가로 셋팅해 주어야 하는 것이다!!
-> AWS_REGION, AWS_SECRET_NAME을 설정해 줄 때 같이 설정해 주면 좋을 것 같다. 🙃

참고 자료

[NEST] nestjs에서 aws secret-manager 사용하기
https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/setting-credentials-node.html

profile
달려보자

0개의 댓글