Проблема с подключением sam local api к менеджеру секретов - PullRequest
0 голосов
/ 08 июля 2019

Я пытаюсь настроить AWS SAM локально, поэтому мне не нужно выполнять развертывание каждый раз, когда я изменяю код. Но у меня проблемы с получением секретов из Менеджера секретов. Я создал новый проект SAM, используя sam init --runtime java

Затем я создал новый секрет в Secret Manager и изменил код в функции HelloWorld, чтобы попытаться получить секрет.

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)

Но это тот же код, чтобы получить секрет, который был дан в менеджере секретов. Разве невозможно подключиться к реальным сервисам AWS от sam local? У меня была похожая проблема с DynamoDB, но я смог заставить ее работать с помощью DynamoDB Local.

Есть ли какие-либо предложения о том, как подключиться к настоящему менеджеру секретов или каким-то образом подделать его локально?

1 Ответ

0 голосов
/ 11 июля 2019

Когда вы запускаете DynamoDB Local, он фактически запускает фиктивный сервер DDB в потоке (или как локальный процесс, в зависимости от того, как вы его запускаете) в рамках выполняемого вами процесса тестирования. К сожалению, Secrets Manager и другие сервисы AWS не предлагают эквивалентного решения для тестирования.

Однако, если вы получаете ResourceNotFoundException, вероятно, вы смогли успешно подключиться к Secrets Manager. Возможно, соединение с диспетчером секретов использует учетную запись, отличную от той, в которой вы сохранили секрет. Один из способов проверить, какие учетные данные используются в коде, - это использовать STS-идентификатор вызывающего абонента .

...