💻 프로그래밍/AWS

AWS Secret Manager그리고 Lambda Extension

피트웨어 제이 (FitwareJay) 2023. 11. 30. 23:47

 

안녕하세요! 이번 포스팅에서는 AWS Secret Manger 그리고 Lambda extension 사용에 대해서 정리해보려고 합니다. 

 

회사에서 사용 중인 Lambda 서비스에서 하드코딩으로 관리되고 있던 값들을 정리하기 위해 AWS Secret Manager를 사용하기로 논의가 되었습니다. 해당 서비스가 자주 업데이트 되는 서비스가 아니었어서 유지보수 하기 어려운 형태였는데요. 시간이 지나고 보니 생각보다 중요한 레거시(?)가 돼서 지금이라도 유지보수를 위해 정비를 하게 되었습니다.

 

1. 하드코딩 된 값들을 제거함으로써 dev, stg, prd 환경에서 동일한 코드로 관리

2. 이런 값들을 Secret으로 빼서 보안성 높이기

 

크게 위 두가지 목표를 가지고 작업을 시작했습니다.

 

1. AWS Secret Manager란?


출처: https://aws.amazon.com/ko/secrets-manager/

AWS Secret Manager는 데이터베이스 보안 인증정보 혹은 api key와 같은 정보들을 안전하게 암호화하고 중앙집중식으로 관리할 수 있는 서비스입니다. 말 그대로 시크릿 매니저입니다ㅋㅋ

 

콘솔에서 AWS Secret Manager를 추가하는 과정

Secret Manager 사용하는 방법도 크게 어렵진 않은데요. 콘솔로 Secret Manager를 생성하고 키/값을 추가하면 끝입니다. 이후 Secret Manger 이름을 정의하고 생성하면 끝! 저는 test/lambda/jay로 이름을 지정했습니다~

 

샘플코드까지 줘서 개꿀

Secret Manager를 생성하면 여러 언어로 샘플코드까지 줘서 테스트하는데 크게 어렵지 않습니다. 해당 코드를 복사하고 Lambda에 추가해서 배포해보겠습니다.

import {
  SecretsManagerClient,
  GetSecretValueCommand,
} from "@aws-sdk/client-secrets-manager";

export const handler = async (event) => {
  const secretName = "test/lambda/jay"; // 시크릿 매니저 이름
  const client = new SecretsManagerClient({
    region: "ap-northeast-2",
  });
  let result;
  
  try {
    result = await client.send(
      new GetSecretValueCommand({
        SecretId: secretName,
        VersionStage: "AWSCURRENT", // VersionStage defaults to AWSCURRENT if unspecified
      })
    );
  } catch (error) {
    throw error;
  }
  
  const secret = result.SecretString;
  const response = {
    statusCode: 200,
    body: JSON.stringify(secret),
  };
  return response;
};

 

위 코드는 샘플코드 그대로 가져왔으며 Secret Manager에 접근해서 secret들을 가져온 뒤 response로 전달하고 있습니다. 실제로 그렇게 동작할까요?

 

Exception 발생

익셉션(Exception)이 발생했네요 ㅋㅋㅋ 내용을 확인해 보면...

jayLambdaTest is not authorized to perform: secretsmanager:GetSecretValue on resource: test/lambda/jay because no identity-based policy allows the secretsmanager:GetSecretValue action"

 

역시 엄격한 AWS! 위 내용은 Lambda에서 test/lambda/jay 라는 Secret Manager의 GetSecretValue 액션을 허용하는 정책이 없기 때문에 접근이 불가하다는 말입니다. 당연하죠~?! 저희는 서비스 별로 권한을 분리하고 특정 서비스에서는 특정 리소스만 사용하게 해야 보안도 높일 수 있고 관리도 편합니다.

 

IAM role에서 Lambda의 역할을 확인

 

현재는 기본 권한 정책만 존재하기 때문에 test/lambda/jay lambda에 접근할 수 있는 권한정책을 추가해 보겠습니다.

 

권한 추가 버튼을 클릭후 Secret Manager를 선택

저희는 GetSecretValue 액션만 필요하기 때문에 해당 옵션만 선택하고 리소스를 특정합니다. 여기서 특정 리소스는 접근하고자 하는 Secret Manager의 ARN을 말합니다. 내용을 모두 입력 후 저장한 후 다시 Lambda를 호출해 보겠습니다.

 

정상적으로 Secret 값 들을 반환!!

호출 결과를 보시면 정상적으로 Secret Manager의 값들을 가져온 것을 확인할 수 있습니다!! 오예!!

 

 

2. SecretManager를 그대로 쓰면 안 되는 이유!


소중한 회삿돈...

위 내용에서 끝난 줄 알았지만 사실 끝이 아닙니다! Secret Manager 호출하는 것도 모두 '돈'입니다 ㅋㅋㅋ 저희는 회사에 소속되어 있기 때문에 AWS 리소스를 최적화해서 사용할 의무가 있습니다~

 

AWS 요금 계산기로 계산해본 예상 비용

엇... 이렇게 보니까 생각보다 안 비싸네... 여하튼 트래픽이 늘어나고 사용하는 보안암호(Secret)들이 많아질수록 요금은 올라가겠죠? 그리고 매번 Lambda에서 Secret Manager를 호출하는 것 자체가 응답속도에 영향을 주는 행위입니다!

 

그래서 왜 이렇게 말이 길었느냐?! 위 문제들을 어느 정도 해소해 줄 수 있는 방법이 있습니다! 바로 Lambda Extension 중 하나인 AWS-Parameters-and-Secrets-Lambda-Extension 입니다!!

 

출처: https://aws.amazon.com/ko/blogs/compute/using-the-aws-parameter-and-secrets-lambda-extension-to-cache-parameters-and-secrets/

 

 

AWS-Parameters-and-Secrets-Lambda-Extension을 사용하면 시크릿을 검색한 후 로컬 캐시에 저장합니다. 그런 다음 캐시 된 값은 만료될 때까지 이후 호출에 사용됩니다. 캐시된 값은 TTL(time-to-live)이 경과한 이후에 만료되며 SECRETS_MANAGER_TTL 환경변수로 TTL 시간을 조절할 수 있습니다. (default 300초)

 

익스텐션 이름 그대로 AWS Parameter Store도 동일하게 사용할 수 있습니다. 이렇게 캐시를 사용하게 되면 Secret Manager API를 계속 호출하지 않으니 비용도 감소되고 Lambda의 응답시간도 빨라질 것입니다.

 

자! 그럼 AWS-Parameters-and-Secrets-Lambda-Extension을 추가해 보도록 하겠습니다

 

처음엔 Layers에 아무것도 추가가 안되어 있습니다
Layer 추가를 하게되면 위 내용처럼 Extension을 선택할 수 있습니다
Layer가 한개 추가된 걸 확인할 수 있습니다.

이제 코드를 수정해 보겠습니다. Lambda에서는 더 이상 직접적으로 Secret Manager를 호출하는 게 아니라 Extension을 통해서 호출하게 됩니다. (캐싱된 값이 없을 때만)

export const handler = async (event) => {
  const secretName = "test/lambda/jay"; // 시크릿 매니저 이름
  const url = `http://localhost:${process.env.PARAMETERS_SECRETS_EXTENSION_HTTP_PORT}/secretsmanager/get?secretId=${secretName}`;
  const options = {
    headers: { 'X-Aws-Parameters-Secrets-Token': process.env.AWS_SESSION_TOKEN },
    method: 'GET',
  };
  let result;
  
  try {
    const response = await fetch(url, options);
    if (!response.ok) {
      const json = await response.json().catch((err) => err.message);
      console.error('Invalid response :', json);
      throw new Error(`Invalid ${response.status} response`);
    }
    result = await response.json();

  } catch (error) {
    console.error('Error:', error);
    throw error;
  }
  
  return {
    statusCode: 200,
    body: JSON.parse(result.SecretString)
  };
};

Extension port를 환경변수로 지정해줘야 합니다. (default: 2773)
응답 결과

 

Lambda Extension 호출은 localhost를 호출하게 되며 Secret Manager, Parameter Store 별 API endpoint가 존재합니다. 자세한 내용은 여기서 확인 가능합니다.

 

 

3. 참고


 

Lambda Extensions API - AWS Lambda

Lambda Extensions API Lambda function authors use extensions to integrate Lambda with their preferred tools for monitoring, observability, security, and governance. Function authors can use extensions from AWS, AWS Partners, and open-source projects. For m

docs.aws.amazon.com

 

Using the AWS Parameter and Secrets Lambda extension to cache parameters and secrets | Amazon Web Services

Caching data retrieved from external services is an effective way to improve the performance of your Lambda function and reduce costs. Implementing a caching layer has been made simpler with this AWS-managed Lambda extension. 

aws.amazon.com

 

Attach a permissions policy to an AWS Secrets Manager secret - AWS Secrets Manager

The following put-resource-policy example adds a permissions policy to a secret, checking first that the policy does not provide broad access to the secret. The policy is read from a file. For more information, see Loading AWS CLI parameters from a file in

docs.aws.amazon.com

 

How To Cache Secrets Using AWS Lambda Extensions | HackerNoon

Build a cache layer for secrets stored in AWS Secrets manager using AWS Lambda extension

hackernoon.com

 

AWS Lambda 함수에서 AWS Secrets Manager 보안 암호 사용 - AWS Secrets Manager

이 페이지에 작업이 필요하다는 점을 알려 주셔서 감사합니다. 실망시켜 드려 죄송합니다. 잠깐 시간을 내어 설명서를 향상시킬 수 있는 방법에 대해 말씀해 주십시오.

docs.aws.amazon.com

 

AWS Lambda 함수에서 Parameter Store 파라미터 사용 - AWS Systems Manager

AWS Lambda 함수에서 Parameter Store 파라미터 사용 AWS Systems Manager의 기능인 Parameter Store는 구성 데이터 관리 및 암호 관리를 위한 안전한 계층적 스토리지를 제공합니다. 암호, 데이터베이스 문자열, A

docs.aws.amazon.com