简体   繁体   English

无法从运行 Java 的 Lambda 检索 AWS 机密

[英]Unable to retrieve AWS Secrets from Lambda running Java

I am writing a AWS Lambda function that will handle requests from discord.我正在编写一个 AWS Lambda 函数来处理来自 discord 的请求。 I am storing my discord values in AWS SecretsManager and need to retrieve them so I can verify the requests.我将我的 discord 值存储在 AWS SecretsManager 中并需要检索它们以便我可以验证请求。

I have my lambda set to time out after 30 seconds and when my lambda runs it times out and never get the secrets value.我将我的 lambda 设置为在 30 秒后超时,当我的 lambda 运行时超时并且永远不会获得秘密值。 I ran the same code in my IDE and it was able to fetch the values.我在我的 IDE 中运行相同的代码,它能够获取值。 I even assumed the role of my lambda and was able to execute the code in my IDE as well.我什至承担了我的 lambda 的角色,并且也能够在我的 IDE 中执行代码。 The lambda role has the following permissions: lambda 角色具有以下权限:

secretsmanager:GetSecretValue, secretsmanager:DescribeSecret, secretsmanager:ListSecrets

I even gave the lambda role read permissions to the secret value.我什至授予 lambda 角色读取秘密值的权限。 Would anyone know why its timing out in the lambda and not getting the value?有人知道为什么它在 lambda 中超时而没有获得价值吗? Here is my lambda handler class.这是我的 lambda 处理程序类。

public class HandlerStream implements RequestHandler<DiscordEventRequest, DiscordEventResponse> {
  DiscordSecrets discordSecrets;
  Gson gson = new GsonBuilder().setPrettyPrinting().create();

  @Override
  public DiscordEventResponse handleRequest(DiscordEventRequest event, Context context) {
    LambdaLogger logger = context.getLogger();

    logger.log(String.format("Received Event: %s", gson.toJson(event)));
    try {
      getDiscordSecrets(logger);

      DiscordEventResponse response = new DiscordEventResponse();
      switch (event.getJsonBody().getType()) {
        case 1:
          response.setType(1);
      }

      return response;
    } catch (Throwable ex) {
      logger.log("Exception occurred when executing lambda: " + ex.getMessage());
    }
   throw new RuntimeException("[UNAUTHORIZED] invalid state detected");
  }

  private DiscordSecrets getDiscordSecrets(LambdaLogger logger) {
    if (discordSecrets == null) {
      String tokenName = System.getenv("discordToken");

      logger.log("Token Name " + tokenName);

      AWSSecretsManager client = AWSSecretsManagerClientBuilder.standard().build();

      GetSecretValueRequest request = new GetSecretValueRequest().withSecretId(tokenName);

      GetSecretValueResult response = client.getSecretValue(request);

      String secret;

      logger.log("Got secret value");

      if (response.getSecretString() != null) {
        secret = response.getSecretString();
      } else {
        secret = new String(Base64.getDecoder().decode(response.getSecretString().getBytes(StandardCharsets.UTF_8)));
      }
      discordSecrets = gson.fromJson(secret, DiscordSecrets.class);
      logger.log("Discord Secrets " + gson.toJson(discordSecrets));
    }
    return discordSecrets;
  }
}

This is what is returned from the lambda (I changed it to 5 seconds for quicker time outs but it was timing out after 30 seconds as well)这是从 lambda 返回的内容(我将其更改为 5 秒以便更快超时,但它也在 30 秒后超时)

2021-09-28T00:11:12.827-05:00   START RequestId: e5e211d0-9307-4609-9939-ff54f876e516 Version: $LATEST
2021-09-28T00:11:13.321-05:00   Received Event: { "jsonBody": { "type": 1, "version": 0 } }
2021-09-28T00:11:13.321-05:00   Token Name DiscordToken
2021-09-28T00:11:17.842-05:00   END RequestId: e5e211d0-9307-4609-9939-ff54f876e516
2021-09-28T00:11:17.842-05:00   REPORT RequestId: e5e211d0-9307-4609-9939-ff54f876e516 Duration: 5005.29 ms Billed Duration: 5000 ms Memory Size: 128 MB Max Memory Used: 102 MB Init Duration: 492.26 ms
2021-09-28T00:11:17.842-05:00   2021-09-28T05:11:17.833Z e5e211d0-9307-4609-9939-ff54f876e516 Task timed out after 5.01 seconds

It never hits the "Got secret value" nor does it throw an exception.它永远不会达到“Got secret value”,也不会抛出异常。 All it does it wait until eventually the lambda times out.它所做的一切都等到 lambda 最终超时。

Any help would be appreciated任何帮助,将不胜感激

Update I updated my lambda to use the v2 of the client as follows更新我更新了我的 lambda 以使用客户端的 v2,如下所示

private DiscordSecrets getDiscordSecrets(LambdaLogger logger) {
    if (discordSecrets == null) {
      String tokenName = System.getenv("discordToken");

      logger.log("Token Name " + tokenName);
      logger.log("Creating Client");
      SecretsManagerClient client = SecretsManagerClient.builder().region(Region.US_EAST_2).build();
      logger.log("Done creating client");
      String secret;

      GetSecretValueRequest request = GetSecretValueRequest.builder().secretId(tokenName).build();
      GetSecretValueResponse response = client.getSecretValue(request);

      logger.log("Got secret value");

      if (response.secretString() != null) {
        secret = response.secretString();
      } else {
        secret = new String(Base64.getDecoder().decode(response.secretBinary().asByteBuffer()).array());
      }
      discordSecrets = gson.fromJson(secret, DiscordSecrets.class);
      logger.log("Discord Secrets " + gson.toJson(discordSecrets));
    }
    return discordSecrets;
  }

It looks like it is hanging on trying to create the client.看起来它正在尝试创建客户端。 As it times out before Done creating client happens.因为它在Done creating client发生之前超时。 IT also was hanging getting the client with the old method as well. IT 也一直在用旧方法获取客户。

Troubleshooting steps:故障排除步骤:

  1. Please specify the region while creating the client.创建客户端时请指定区域。
AWSSecretsManager client = AWSSecretsManagerClientBuilder.standard().withRegion(Regions.<YOUR_REGION>).build();

Please refer: https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/secretsmanager/AWSSecretsManagerClientBuilder.html请参考: https ://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/secretsmanager/AWSSecretsManagerClientBuilder.html

  1. If this does not work and the lambda is still timing out define a VPC endpoint for the SecreteManager service.如果这不起作用并且 lambda 仍然超时,请为 SecreteManager 服务定义一个 VPC 端点。

Please refer: https://heathivie.com/2020/08/13/aws-lambda-and-secrets-manager-timeout/请参考: https ://heathivie.com/2020/08/13/aws-lambda-and-secrets-manager-timeout/

Regards Amit问候阿米特

I figured out the issue.我想通了这个问题。 The problem was that Java Lambdas need time to spin up and then initialize the SecretsManager client which caused the time.问题是 Java Lambdas 需要时间来启动然后初始化导致时间的 SecretsManager 客户端。

I ended up making the client static我最终使客户端静态

public class HandlerStream implements RequestStreamHandler {
  static SecretsManagerClient client = SecretsManagerClient.builder().build();
  ...
}

Even after that I got an out of memory exception so I increased the memory of the lambda to 256 which seemed to solve the problem.即使在那之后我遇到了内存不足的异常,所以我将 lambda 的内存增加到 256,这似乎解决了问题。 Some reason the lambda is using 146 mb of memory upon execution.由于某些原因,lambda 在执行时使用了 146 mb 的内存。 I dont know if this is due to how it handles java or not.我不知道这是否是由于它处理 java 的方式所致。

I ran into this problem when creating a lambda using Terraform.我在使用 Terraform 创建 lambda 时遇到了这个问题。 I'd not set a value for the timeout of the lambda and the default timeout value for Lambda execution is 3 seconds.我没有为 lambda 的超时设置值,Lambda 执行的默认超时值为 3 秒。

It was taking longer than 3 seconds to create the secretsmanager client using the Java SDK builder so my Lambda was hitting the execution timeout on every execution.使用 Java SDK 构建器创建 secretsmanager 客户端花费的时间超过 3 秒,因此我的 Lambda 在每次执行时都会遇到执行超时。

Facepalm.捂脸。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM