Попытка расшифровать зашифрованный текст в функции Lambda с использованием KMS приводит к таймауту

При расшифровке зашифрованного текста из командной строки с использованием AWS CLI шифротекст дешифруется без проблем:

$ aws kms decrypt --ciphertext-blob fileb://encrypted-secrets --output text --query Plaintext --region us-east-1 | base64 --decode > decryped-secrets

Эта операция дешифрования также работает локально при попытке сделать это из js script:

#!/usr/local/bin/node

const fs = require('fs');
const AWS = require('aws-sdk');
const kms = new AWS.KMS({region:'us-east-1'});

const secretPath = './encrypted-secrets';
const encryptedSecret = fs.readFileSync(secretPath);

const params = {
      CiphertextBlob: encryptedSecret
};

kms.decrypt(params, function(err, data) {
  if (err) {
    console.log(err, err.stack);
  } else {
    const decryptedScret = data['Plaintext'].toString();
    console.log('decrypted secret', decryptedScret);
  }
});

Однако при попытке сделать это с почти тем же самым точным кодом, что и выше, в контексте функции AWS Lambda, вызов функции приводит к таймауту:

'use strict';

const zlib = require('zlib');
const mysql = require('mysql');
const fs = require('fs');
const AWS = require('aws-sdk');
const kms = new AWS.KMS({region:'us-east-1'});

const secretPath = './encrypted-secrets';
const encryptedSecret = fs.readFileSync(secretPath);

const params = {
    CiphertextBlob: encryptedSecret
};

exports.handler = (event, context, callback) => {
    kms.decrypt(params, (err, data) => {
       if (err) {
            console.log(err, err.stack);
            return callback(err);
        } else {
            const decryptedScret = data['Plaintext'].toString();
            console.log('decrypted secret', decryptedScret);
            return callback(null, `Successfully processed ${parsed.logEvents.length} log events.`);
        }
    });
};

журнал тайм-аута:

START RequestId: start-request-id-redacted Version: $LATEST
END RequestId: end-request-id-redacted
REPORT RequestId: report-requested-id-redacted  Duration: 10002.43 ms   Billed Duration: 10000 ms   Memory Size: 128 MB Max Memory Used: 18 MB  
2016-11-13T19:22:28.774Z task-id-redacted Task timed out after 10.00 seconds

Примечания:

  • Если я прокомментирую вызов kms.decrypt и попытаюсь console.log params или что-то действительно, значения выводятся без проблем. Кажется, что есть проблема с вызовом kms.decrypt, и никакая действительная ошибка за пределами таймаута не возвращается.
  • Политика, связанная с ролью, в которой вызывается функция лямбда, содержит прилагаемую политику AWSLambdaVPCAccessExecutionRole, а также следующую встроенную политику:

policygen-lambda_basic_execution_and_kms_decrypt-201611131221:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "sid-redacted",
            "Effect": "Allow",
            "Action": [
                "kms:Decrypt"
            ],
            "Resource": [
                "arn:aws:kms:us-east-1:account-redacted:key/key-id-redacted"
            ]
        }
    ]
}
  • Я отредактировал любую идентификационную информацию из кода.

Ответы

Ответ 1

После тщательных бесед с пользователями поддержки AWS, которые были очень полезны, у нас есть ответ:

Основная причина, по которой произошел тайм-аут, была связана с отсутствием возможности подключения изнутри функции Lambda к службе KMS из-за того, что служба KMS не имела конечной точки в VPC, где была настроена функция Lambda.

Чтобы функция Lambda в VPC подключалась к любой службе, отличной от Amazon S3, которая имеет конечную точку в VPC, функция лямбда должна быть расположена в /, связанной, по меньшей мере, с одним, но предпочтительно двумя частными подсетей с их таблицами маршрутизации, включая маршрут назначения 0.0.0.0/16 к шлюзу NAT.

Невозможно, чтобы функция Lambda находилась в общедоступной подсети с интернет-шлюзом.

Шаги для получения Лямбда-функции, связанной с VPC, для доступа к KMS и всем другим службам, которые не имеют конечных точек VPC:

  • Создайте или обратите внимание на существующую личную подсеть, которая имеет запись таблицы маршрутизации для 0.0.0.0/0 для шлюза NAT.
    • Если у вас еще нет шлюза NAT, таблицы маршрутизации и подсети, как указано выше, вам необходимо сначала создать и связать их друг с другом.
  • Прикрепите функцию Lambda к закрытым подсетям выше, при создании функции Lambda или отредактируйте функцию Lambda для этой конфигурации.

Если вы выполните эти два шага, вы сможете вызывать kms.encrypt и другие запросы из вашей лямбда-функции, которые требуют исходящего/исходящего подключения к Интернету, из-за того, что эти службы не имеют конечных точек в вашем VPC.

Визуальный обзор того, как Lambda работает в VPC

Ответ 2

Чтобы добавить к отличному ответу zealoushacker, вы также должны проверить, что параметры вашей группы безопасности лямбды имеют исходящее правило, которое указывает на 0.0.0.0 и любой порт.

В нашем случае мы уже работали в частных подсетях, но в нашу базу данных RDS были ограничены группы безопасности.

Ответ 3

Экземпляры EC2 по умолчанию имеют свой собственный общедоступный IP-адрес, поэтому у них нет проблем с доступом к любым службам, требующим доступа к Интернету (например, KMS).

Лямбда-функции, подключенные к VPC, не имеют открытого IP-адреса, поэтому для доступа к сервису через Интернет (например, KMS) вам необходимо настроить NAT так же, как описано zealoushacker.