1

我正在尝试在本地设置 AWS SAM,这样我就不必在每次更改代码时都进行部署。但我无法从 Secrets Manager 中获取秘密。我使用创建了一个新的 SAM 项目sam init --runtime java

然后,我在 Secret Manager 中创建了一个新密钥,并更改了 HelloWorldFunction 中的代码以尝试检索该密钥。

package helloworld;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.secretsmanager.AWSSecretsManager;
import com.amazonaws.services.secretsmanager.AWSSecretsManagerClientBuilder;
import com.amazonaws.services.secretsmanager.model.*;

/**
 * Handler for requests to Lambda function.
 */
public class App implements RequestHandler<Object, Object> {

    public Object handleRequest(final Object input, final Context context) {
        Map<String, String> headers = new HashMap<>();
        headers.put("Content-Type", "application/json");
        headers.put("X-Custom-Header", "application/json");
        try {
            String secretName = "testsecret";
            String region = "us-west-2";

            // Create a Secrets Manager client
            AWSSecretsManager client  = AWSSecretsManagerClientBuilder.standard()
                                            .withRegion(region)
                                            .build();

            String secret, decodedBinarySecret;
            GetSecretValueRequest getSecretValueRequest = new GetSecretValueRequest()
                            .withSecretId(secretName);
            GetSecretValueResult getSecretValueResult = null;

            try {
                getSecretValueResult = client.getSecretValue(getSecretValueRequest);
            } catch (DecryptionFailureException e) {
                // Secrets Manager can't decrypt the protected secret text using the provided KMS key.
                // Deal with the exception here, and/or rethrow at your discretion.
                throw e;
            } catch (InternalServiceErrorException e) {
                // An error occurred on the server side.
                // Deal with the exception here, and/or rethrow at your discretion.
                throw e;
            } catch (InvalidParameterException e) {
                // You provided an invalid value for a parameter.
                // Deal with the exception here, and/or rethrow at your discretion.
                throw e;
            } catch (InvalidRequestException e) {
                // You provided a parameter value that is not valid for the current state of the resource.
                // Deal with the exception here, and/or rethrow at your discretion.
                throw e;
            } catch (ResourceNotFoundException e) {
                System.out.println(e.getMessage());

                StringWriter outError = new StringWriter();
                e.printStackTrace(new PrintWriter(outError));
                System.out.println(outError.toString());
                // We can't find the resource that you asked for.
                // Deal with the exception here, and/or rethrow at your discretion.
                throw e;
            }

            // Decrypts secret using the associated KMS CMK.
            // Depending on whether the secret is a string or binary, one of these fields will be populated.
            if (getSecretValueResult.getSecretString() != null) {
                secret = getSecretValueResult.getSecretString();
                return new GatewayResponse(secret, headers, 200);
            }
            else {
                decodedBinarySecret = new String(Base64.getDecoder().decode(getSecretValueResult.getSecretBinary()).array());
                return new GatewayResponse(decodedBinarySecret, headers, 200);
            }
        } catch (Exception e) {
            return new GatewayResponse("{}", headers, 500);
        }
    }
}

当我运行sam local start-api并导航到 时http://127.0.0.1:3000/hello,我收到此错误:

Secrets Manager can’t find the specified secret. (Service: AWSSecretsManager; Status Code: 400; Error Code: ResourceNotFoundException; Request ID: 6881467f-d968-4f4e-ae60-7e3128124cc5)
com.amazonaws.services.secretsmanager.model.ResourceNotFoundException: Secrets Manager can’t find the specified secret. (Service: AWSSecretsManager; Status Code: 400; Error Code: ResourceNotFoundException; Request ID: 6881467f-d968-4f4e-ae60-7e3128124cc5)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleErrorResponse(AmazonHttpClient.java:1632)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeOneRequest(AmazonHttpClient.java:1304)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeHelper(AmazonHttpClient.java:1058)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:743)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:717)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:699)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.access$500(AmazonHttpClient.java:667)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.java:649)
    at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:513)
    at com.amazonaws.services.secretsmanager.AWSSecretsManagerClient.doInvoke(AWSSecretsManagerClient.java:2024)
    at com.amazonaws.services.secretsmanager.AWSSecretsManagerClient.invoke(AWSSecretsManagerClient.java:2000)
    at com.amazonaws.services.secretsmanager.AWSSecretsManagerClient.executeGetSecretValue(AWSSecretsManagerClient.java:878)
    at com.amazonaws.services.secretsmanager.AWSSecretsManagerClient.getSecretValue(AWSSecretsManagerClient.java:853)
    at helloworld.App.handleRequest(App.java:53)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at lambdainternal.EventHandlerLoader$PojoMethodRequestHandler.handleRequest(EventHandlerLoader.java:259)
    at lambdainternal.EventHandlerLoader$PojoHandlerAsStreamHandler.handleRequest(EventHandlerLoader.java:178)
    at lambdainternal.EventHandlerLoader$2.call(EventHandlerLoader.java:888)
    at lambdainternal.AWSLambda.startRuntime(AWSLambda.java:293)
    at lambdainternal.AWSLambda.<clinit>(AWSLambda.java:64)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:348)
    at lambdainternal.LambdaRTEntry.main(LambdaRTEntry.java:114)

但是,获取秘密管理器中提供的秘密的代码相同。不能从 sam local 连接到真正的 AWS 服务吗?我在使用 DynamoDB 时遇到了类似的问题,但能够通过使用 DynamoDB Local 来处理它。

关于如何连接到真正的秘密管理器或以某种方式在本地伪造它的任何建议?

4

1 回答 1

2

当您运行 DynamoDB Local 时,它实际上是在您运行的测试进程中的线程中运行模拟 DDB 服务器(或作为本地进程,取决于您如何启动它)。不幸的是,Secrets Manager 和其他 AWS 服务不提供等效的测试解决方案。

但是,如果您返回 ResourceNotFoundException,您似乎能够成功连接到 Secrets Manager。与机密管理器的连接可能使用的帐户与您存储机密的帐户不同。检查代码使用的凭据的一种方法是使用STS 获取调用者身份调用。

于 2019-07-11T03:26:25.090 回答