AWS Secrets Manager용 단순 캐시

소개



AWS Secrets Manager에서 일부 암호에 액세스해야 하는 경우 값을 캐시하는 것이 좋습니다. 이렇게 하면 덜 자주 가져오고 비용을 절약할 수 있습니다. 안타깝게도 NodeJS용으로 내장되어 있지 않습니다aws-sdk. 다행히도 구현이 매우 간단합니다.

이 게시물에서는 이것이 왜 좋은 생각인지 그리고 AWS Lambda 함수를 사용할 때 이를 수행하는 한 가지 방법을 살펴보겠습니다. 제공된 구현은 TypeScript에 있습니다.

값을 캐시해야 하는 이유



모든 외부 통화는 위험하며 잘못될 수 있는 많은 일이 있습니다. 네트워크가 신뢰할 수 없습니다. 한 번은 값을 가져오기 위한 비율 할당량에 도달했고 서비스가 응답을 기다리다가 결국 시간 초과되었습니다.

캐시된 값을 검색하는 것이 더 빠르고 몇 줄의 코드만으로 비용을 절약할 수 있습니다. AWS Secrets Manager에 대한 호출을 절약할 수 있을 뿐만 아니라 기간도 단축됩니다.

전략



AWS Lambda 함수가 처음 실행될 때 아직 실행 환경이 없는 경우 실행 환경을 생성합니다. 실행이 완료되면 해당 환경은 후속 실행을 위해 일정 시간 동안 사용 가능한 상태로 유지됩니다.

환경에서 객체를 생성하여 이를 간단한 캐싱 메커니즘으로 사용할 수 있습니다. 해당 개체에 값을 넣으면 다음에 함수가 호출될 때 액세스할 수 있습니다.

구현



두 가지 구성 요소로 나누어 보겠습니다. 먼저 캐싱을 위한 구성 요소:

class SimpleCache {
  private cache: Record<string, string> = {};
  constructor(private readonly loadValue: (key: string) => Promise<string | undefined>) {}
  async get(key: string) {
    // if we find the value in the cache, return immediately
    if (this.cache[key]) {
      return this.cache[key];
    }
    // load it with the provided function
    const res = await this.loadValue(key);
    if (res == null) {
      return res;
    }
    // put the value in the cache and return.
    // The next time we need the value, we don't have to fetch it again.
    this.cache[key] = res;
    return res;
  }
}


그런 다음 주어진 키로 비밀 값을 가져오기 위한 구성 요소:

import SecretsManager from 'aws-sdk/clients/secretsmanager';

const secretsClient = new SecretsManager();
const client = new SimpleCache((key) =>
  secretsClient
    .getSecretValue({ SecretId: key })
    .promise()
    .then((x) => x.SecretString),
);


함께 모아서:

import SecretsManager from 'aws-sdk/clients/secretsmanager';

class SimpleCache {
  private cache: Record<string, string> = {};
  constructor(private readonly loadValue: (key: string) => Promise<string | undefined>) {}
  async get(key: string) {
    if (this.cache[key]) {
      return this.cache[key];
    }
    const res = await this.loadValue(key);
    if (res == null) {
      return res;
    }
    this.cache[key] = res;
    return res;
  }
}

// When we create these two instances outside of the handler 
// function, they are only created the first time a new 
// execution environment is created. This allows us to use it as a cache.
const secretsClient = new SecretsManager();
const client = new SimpleCache((key) =>
  secretsClient
    .getSecretValue({ SecretId: key })
    .promise()
    .then((x) => x.SecretString),
);

export const handler = async () => {
  // the client instance will be reused across execution environments
  const secretValue = await client.get('MySecret');
  return {
    statusCode: 200,
    body: JSON.stringify({
      message: secretValue,
    }),
  };
};


추가 사용량



다른 통합에 대해 위의 SimpleCache 구현을 사용할 수 있습니다. 네트워크를 통해 다른 정적 값을 가져오는 경우 동일한 캐싱 메커니즘을 사용할 수 있습니다.

예를 들어 aws-sdk v3를 사용하기로 결정한 경우 동일한 SimpleCache를 사용할 수 있지만 SecretsManager와 관련된 구성 요소를 변경할 수 있습니다. V3에는 .promise() 로 엉망이 될 필요가 없는 더 나은 구문이 있습니다.

환경 변수에 비밀을 넣지 마십시오.



배포 중에 AWS Secrets Manager의 값을 확인하고 환경 변수에 넣을 수 있습니다.

불행하게도 이것은 공격자가 귀하의 비밀을 일반 텍스트로 사용할 수 있음을 의미합니다. 그들이 가장 먼저 찾는 곳 중 하나입니다. 그것은 전에 일어났고 아마도 다시 일어날 것입니다. Here's an example of an attack like that. .

결론



이 게시물에서는 AWS Secrets Manager에서 값을 캐싱해야 하는 이유를 다루었습니다. 비용을 절약하고 코드의 안정성과 성능을 향상시킬 수 있습니다. 이를 달성하는 방법에 대한 구현도 있습니다.

이 게시물이 도움이 되셨다면 여기와 에서 저를 팔로우해 주세요.

읽어 주셔서 감사합니다!

좋은 웹페이지 즐겨찾기