View a markdown version of this page

Tratamento da exclusividade com o Lambda SnapStart - AWS Lambda

Tratamento da exclusividade com o Lambda SnapStart

Quando as invocações aumentam a escala verticalmente em uma função do SnapStart, o Lambda usa um único snapshot inicializado para retomar diversos ambientes de execução. Se o código de inicialização gerar conteúdo exclusivo que é incluído no snapshot, o conteúdo poderá não ser exclusivo quando for reutilizado em ambientes de execução. Para manter a exclusividade ao usar o SnapStart, você deve gerar conteúdo exclusivo após a inicialização. Isso inclui IDs exclusivos, segredos exclusivos e entropia que são usados para gerar a pseudoaleatoriedade.

Recomendamos as práticas recomendadas a seguir para ajudar você a manter a exclusividade em seu código. Para funções do Java, o Lambda também fornece uma ferramenta de verificação do SnapStart de código aberto para ajudar a verificar o código que assume exclusividade. Se você gerar dados exclusivos durante a fase de inicialização, poderá usar um hook de runtime para restaurar a exclusividade. Com hooks de runtime, é possível executar um código específico imediatamente antes que o Lambda obtenha um snapshot ou imediatamente após o Lambda retornar uma função de um snapshot.

Evite salvar um estado que depende da exclusividade durante a inicialização

Durante a fase de inicialização da função, evite armazenar em cache dados que devem ser exclusivos, como a geração de um ID exclusivo para registro em log ou a aplicação de sementes para funções aleatórias. Em vez disso, recomendamos gerar dados exclusivos ou definir sementes para funções aleatórias dentro do manipulador da função ou usar um hook de runtime.

Os exemplos a seguir demonstram como gerar um UUID no manipulador de função.

Java
exemplo: geração de um ID exclusivo no manipulador de função
import java.util.UUID; public class Handler implements RequestHandler<String, String> { private static UUID uniqueSandboxId = null; @Override public String handleRequest(String event, Context context) { if (uniqueSandboxId == null) uniqueSandboxId = UUID.randomUUID(); System.out.println("Unique Sandbox Id: " + uniqueSandboxId); return "Hello, World!"; } }
Python
exemplo: geração de um ID exclusivo no manipulador de função
import json import random import time unique_number = None def lambda_handler(event, context): seed = int(time.time() * 1000) random.seed(seed) global unique_number if not unique_number: unique_number = random.randint(1, 10000) print("Unique number: ", unique_number) return "Hello, World!"
.NET
exemplo: geração de um ID exclusivo no manipulador de função
namespace Example; public class SnapstartExample { private Guid _myExecutionEnvironmentGuid; public SnapstartExample() { // This GUID is set for non-restore use cases, such as testing or if SnapStart is turned off _myExecutionEnvironmentGuid = new Guid(); // Register the method which will run after each restore. You may need to update Amazon.Lambda.Core to see this Amazon.Lambda.Core.SnapshotRestore.RegisterAfterRestore(MyAfterRestore); } private ValueTask MyAfterRestore() { // After restoring this snapshot to a new execution environment, update the GUID _myExecutionEnvironmentGuid = new Guid(); return ValueTask.CompletedTask; } public string Handler() { return $"Hello World! My Execution Environment GUID is {_myExecutionEnvironmentGuid}"; } }

Use geradores de números pseudoaleatórios criptograficamente seguros (CSPRNGs)

Quando o SnapStart está habilitado, o Lambda tira um snapshot do ambiente de execução da função, inclusive toda a memória da aplicação e do sistema. Isso significa que o estado interno de cada gerador de números aleatórios (RNG) é preservado exatamente como estava no momento do snapshot, junto com quaisquer bytes aleatórios que sua aplicação ou suas dependências já tenham gerado e armazenado em buffers de memória.

Quando o Lambda restaura um ambiente de execução a partir de um snapshot, ele inicia novamente o gerador de números aleatórios do kernel de /dev/random e /dev/urandom com uma nova entropia. O software que lê números aleatórios diretamente desses dispositivos mantém a aleatoriedade com o SnapStart.

Se a aplicação depender da aleatoriedade, recomendamos usar geradores de números pseudoaleatórios criptograficamente seguros (CSPRNGs). Além do OpenSSL fornecido pela AL, os runtimes gerenciados pelo Lambda que oferecem suporte ao SnapStart (Java versão 11+, Python versão 3.12+ e .NET versão 8+) incluem os seguintes CSPRNGs integrados:

  • Java: java.security.SecureRandom

  • Python: random.SystemRandom

  • .NET: System.Security.Cryptography.RandomNumberGenerator

nota

Para o runtime do Go Lambda, nenhuma alteração será necessária se suas funções usarem crypto/rand da biblioteca padrão, que é compatível com o SnapStart por padrão.

Quando você empacota sua função como uma imagem de contêiner, sua imagem base determina a compatibilidade exclusiva com o SnapStart:

  • Imagem base do Lambda para um runtime gerenciado (Java versão 11+, Python versão 3.12+ e .NET versão 8+): compatível com o SnapStart, conforme descrito acima.

  • Imagem base provided.al2023: compatível se o runtime da sua linguagem de programação obtiver entropia de /dev/random, /dev/urandom ou da versão compatível com SnapStart do OpenSSL (openssl-snapsafe-libs) listada na Lista de pacotes do Amazon Linux 2023. Se seu runtime depender de outras fontes de entropia, siga as etapas descritas na seção “Sua própria imagem base” abaixo.

  • Sua própria imagem base: audite suas bibliotecas criptográficas e use um hook de runtime após a restauração para descartar qualquer estado do gerador de números aleatórios (RNG) em cache ou bytes aleatórios armazenados em buffer, garantindo que a biblioteca leia a entropia nova do sistema após a restauração. Por exemplo, as funções do Rust que usam rand::rngs::ThreadRng devem chamar reseed() após a restauração. Recomendamos que você crie usando uma imagem base do Lambda sempre que possível. Em particular, se sua imagem base incluir sua própria versão do OpenSSL ou uma bifurcação do OpenSSL (como BoringSSL ou LibreSSL), use a imagem base provided.al2023, que inclui uma compilação do OpenSSL compatível com SnapStart (openssl-snapsafe-libs), ou use AWS libcrypto (AWS-LC).

Versões mínimas de bibliotecas compatíveis

AWSAs bibliotecas de criptografia da mantêm a aleatoriedade automaticamente com o SnapStart, a partir das versões mínimas especificadas na tabela a seguir. Se você usar essas bibliotecas com as funções do Lambda, certifique-se de usar as seguintes versões mínimas ou versões posteriores:

Biblioteca Versão mínima compatível (x86) Versão mínima compatível (ARM)
AWS libcrypto (AWS-LC)

1.16.0

1.30.0

AWS libcrypto FIPS

2.0.13

2.0.13

Se você empacotar as bibliotecas criptográficas anteriores com suas funções Lambda como dependências transitivas usando as bibliotecas a seguir, certifique-se de usar as seguintes versões mínimas ou versões posteriores:

Biblioteca Versão mínima compatível (x86) Versão mínima compatível (ARM)
AWS SDK for Java 2.x

2.23.20

2.26.12

AWSRuntime comum da para Java

0.29.8

0.29.25

Fornecedor de criptografia do Amazon Corretto

2.4.1

2.4.1
Fornecedor de criptografia FIPS do Amazon Corretto

2.4.1

2.4.1

Os exemplos a seguir demonstram como usar CSPRNGs para garantir sequências numéricas exclusivas mesmo quando a função é restaurada de um snapshot.

Java
exemplo: java.security.SecureRandom
import java.security.SecureRandom; public class Handler implements RequestHandler<String, String> { private static SecureRandom rng = new SecureRandom(); @Override public String handleRequest(String event, Context context) { for (int i = 0; i < 10; i++) { System.out.println(rng.next()); } return "Hello, World!"; } }
Python
exemplo: random.SystemRandom
import json import random secure_rng = random.SystemRandom() def lambda_handler(event, context): random_numbers = [secure_rng.random() for _ in range(10)] for number in random_numbers: print(number) return "Hello, World!"
.NET
exemplo: RandomNumberGenerator
using Amazon.Lambda.Core; using System.Security.Cryptography; [assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))] namespace DotnetSecureRandom; public class Function { public string FunctionHandler() { using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) { byte[] randomUnsignedInteger32Bytes = new byte[4]; for (int i = 0; i < 10; i++) { rng.GetBytes(randomUnsignedInteger32Bytes); int randomInt32 = BitConverter.ToInt32(randomUnsignedInteger32Bytes, 0); Console.WriteLine("{0:G}", randomInt32); } } return "Hello World!"; } }

Ferramenta de verificação do SnapStart (somente para Java)

O Lambda fornece uma ferramenta de verificação para Jada a fim de ajudar você a verificar o código que assume exclusividade. A ferramenta de verificação do SnapStart corresponde a um plug-in SpotBugs de código aberto que executa uma análise estática de acordo com um conjunto de regras. A ferramenta de verificação ajuda a identificar possíveis implementações de código que podem quebrar suposições em relação à exclusividade. Para obter instruções de instalação e uma lista de verificações que a ferramenta de verificação executa, consulte o repositório aws-lambda-snapstart-java-rules no GitHub.

Para saber mais sobre como lidar com a exclusividade com o SnapStart, consulte Início mais rápido com o AWS Lambda SnapStart no AWS Compute Blog.