Restringir o acesso a uma origem do URL de função do AWS Lambda
O CloudFront fornece controle de acesso à origem (OAC) para restringir o acesso a uma origem do URL da função do Lambda.
Tópicos
Criar um OAC
Conclua as etapas descritas nos tópicos a seguir para configurar um novo OAC no CloudFront.
Importante
Se você usar os métodos PUT
ou POST
com o URL da função do Lambda, os usuários deverão calcular o SHA256 do corpo e incluir o valor de hash da carga útil no cabeçalho x-amz-content-sha256
ao enviar a solicitação ao CloudFront. O Lambda não é compatível com cargas úteis não conectadas.
Pré-requisitos
Antes de criar e configurar o OAC, você deve ter uma distribuição do CloudFront com um URL da função do Lambda como origem. Para usar o OAC, você deve especificar o AWS_IAM
como valor para o parâmetro AuthType
. Para ter mais informações, consulte Usar um URL da função do Lambda.
Permitir acesso do OAC ao URL de função do Lambda
Antes de criar um OAC ou configurá-lo em uma distribuição do CloudFront, ele deve ter permissão para acessar o URL da função do Lambda. Faça isso depois de criar uma distribuição do CloudFront, mas antes de adicionar o OAC ao URL da função do Lambda na configuração de distribuição.
nota
Para atualizar a política do IAM para o URL da função do Lambda, você deve usar o AWS Command Line Interface (AWS CLI). Não há suporte para a edição da política do IAM no console do Lambda, no momento.
O comando AWS CLI a seguir concede ao serviço de entidade principal (cloudfront.amazonaws.com
) do CloudFront acesso ao URL da função do Lambda. O elemento Condition
na política permite que o CloudFront acesse o Lambda somente quando a solicitação for em nome da distribuição do CloudFront que contém o URL da função do Lambda.
exemplo : o comando AWS CLI para atualizar uma política para permitir acesso somente leitura a um OAC do CloudFront
O comando AWS CLI a seguir permite que a distribuição do CloudFront (
) acesse seu E1PDK09ESKHJWT
do Lambda.FUNCTION_URL_NAME
aws lambda add-permission \ --statement-id "AllowCloudFrontServicePrincipal" \ --action "lambda:InvokeFunctionUrl" \ --principal "cloudfront.amazonaws.com" \ --source-arn "arn:aws:cloudfront::
123456789012
:distribution/E1PDK09ESKHJWT
" \ --function-nameFUNCTION_URL_NAME
nota
Se você criar uma distribuição e ela não tiver permissão para o URL da função do Lambda, é possível selecionar Copy CLI command (Copiar comando CLI) no console do CloudFront e, em seguida, inserir esse comando no seu terminal de linha de comando. Para ter mais informações, consulte Conceder acesso de função aos Serviços da AWS no Guia do desenvolvedor do AWS Lambda.
Criar o OAC
Para criar um OAC, é possível usar o AWS Management Console, o AWS CloudFormation, a AWS CLI ou a API do CloudFront.
Configurações avançadas para controle de acesso à origem
O atributo de OAC do CloudFront inclui configurações avançadas destinadas somente a casos de uso específicos. Use as configurações recomendadas, a menos que você precise usar as configurações avançadas para uma necessidade específica.
O OAC contém uma configuração chamada Signing behavior (Comportamento de assinatura) (no console) ou SigningBehavior
(na API, na CLI e no AWS CloudFormation). Essa configuração fornece as seguintes opções:
- Always sign origin requests (recommended setting) [Sempre assinar solicitações de origem (configuração recomendada)]
-
Recomendamos usar essa configuração, chamada Sign requests (recommended) [Assinar solicitações (recomendado)] no console, ou
always
na API, na CLI e no AWS CloudFormation. Com essa configuração, o CloudFront sempre assina todas as solicitações enviadas ao URL da função do Lambda. - Never sign origin requests (Nunca assinar solicitações de origem)
-
Essa configuração é chamada Do not sign requests (Não assinar solicitações) no console ou
never
na API, na CLI e no AWS CloudFormation. Use essa configuração para desativar o OAC para todas as origens em todas as distribuições que usam esse OAC. Isso pode economizar tempo e esforço em comparação com a remoção individual de um OAC de todas as origens e distribuições que o usam. Com essa configuração, o CloudFront não assina nenhuma solicitação enviada ao URL da função do Lambda.Atenção
Para usar essa configuração, o URL da função do Lambda deve estar acessível de forma pública. Se você usar essa configuração com um URL da função do Lambda que não esteja acessível de forma pública, o CloudFront não poderá acessar a origem. A origem do URL da função do Lambda retorna erros ao CloudFront e o CloudFront transmite esses erros aos visualizadores. Para ter mais informações, consulte Modelo de segurança e autenticação para URLs de função do Lambda no Guia do usuário do AWS Lambda.
- Não substituir o cabeçalho
Authorization
do visualizador (cliente) -
Essa configuração é chamada Do not override authorization header (Não substituir o cabeçalho de autorização) no console ou
no-override
na API, na CLI e no AWS CloudFormation. Use essa configuração quando quiser que o CloudFront assine solicitações de origem somente quando a solicitação do visualizador correspondente não incluir um cabeçalhoAuthorization
. Com essa configuração, o CloudFront transmite o cabeçalhoAuthorization
da solicitação do visualizador quando houver, mas assina a solicitação de origem (adicionando seu próprio cabeçalhoAuthorization
) quando a solicitação do visualizador não inclui um cabeçalhoAuthorization
.Atenção
-
Se usar essa configuração, você deverá especificar a assinatura do Signature versão 4 para o URL da função do Lambda em vez do nome ou CNAME da distribuição do CloudFront. Quando o CloudFront encaminha o cabeçalho
Authorization
da solicitação do visualizador para o URL da função do Lambda, o Lambda valida a assinatura em relação ao host do domínio de URL do Lambda. Se a assinatura não for baseada no domínio de URL do Lambda, o host na assinatura não corresponderá ao host usado pela origem do URL do Lambda. Isso significa que a solicitação falhará, ocasionando um erro de validação da assinatura.
-
Para transmitir o cabeçalho de
Authorization
da solicitação do visualizador, você deve adicionar o cabeçalho deAuthorization
a uma política de cache para todos os comportamentos de cache que usam URLs da função do Lambda associados a esse controle de acesso à origem.
-
Exemplo de código de modelo
Se a origem do CloudFront for um URL da função do Lambda associado a um OAC, você poderá usar o script do Python a seguir para carregar arquivos na função do Lambda com o método POST
.
Esse código pressupõe que você configurou o OAC com o comportamento de assinatura padrão definido como Sempre assinar solicitações para a origem e que você não selecionou a configuração Não substituir o cabeçalho de autorização.
Essa configuração permite que o OAC gerencie a autorização SigV4 corretamente com o Lambda usando o nome de host do Lambda. A carga útil é assinada usando SigV4 da identidade do IAM autorizada para o URL da função do Lambda, que é designada como o tipo IAM_AUTH
.
O modelo demonstra como lidar com valores de hash de carga útil assinados no cabeçalho x-amz-content-sha256 para solicitações POST
do lado do cliente. Esse modelo foi projetado especificamente para gerenciar cargas úteis de dados de formulário. Ele permite o upload seguro de arquivos para um URL da função do Lambda por meio do CloudFront e usa mecanismos de autenticação da AWS para garantir que somente solicitações autorizadas acessem a função do Lambda.
O código inclui as seguintes funcionalidades:
-
Atende ao requisito de incluir o hash da carga útil no cabeçalho x-amz-content-sha256.
-
Usa a autenticação SigV4 para acesso seguro ao AWS service (Serviço da AWS).
-
Permite uploads de arquivos usando dados de formulário de várias partes
-
Inclui tratamento de erros para exceções de solicitação.
import boto3 from botocore.auth import SigV4Auth from botocore.awsrequest import AWSRequest import requests import hashlib import os def calculate_body_hash(body): return hashlib.sha256(body).hexdigest() def sign_request(request, credentials, region, service): sigv4 = SigV4Auth(credentials, service, region) sigv4.add_auth(request) def upload_file_to_lambda(cloudfront_url, file_path, region): # AWS credentials session = boto3.Session() credentials = session.get_credentials() # Prepare the multipart form-data boundary = "------------------------boundary" # Read file content with open(file_path, 'rb') as file: file_content = file.read() # Get the filename from the path filename = os.path.basename(file_path) # Prepare the multipart body body = ( f'--{boundary}\r\n' f'Content-Disposition: form-data; name="file"; filename="{filename}"\r\n' f'Content-Type: application/octet-stream\r\n\r\n' ).encode('utf-8') body += file_content body += f'\r\n--{boundary}--\r\n'.encode('utf-8') # Calculate SHA256 hash of the entire body body_hash = calculate_body_hash(body) # Prepare headers headers = { 'Content-Type': f'multipart/form-data; boundary={boundary}', 'x-amz-content-sha256': body_hash } # Create the request request = AWSRequest( method='POST', url=cloudfront_url, data=body, headers=headers ) # Sign the request sign_request(request, credentials, region, 'lambda') # Get the signed headers signed_headers = dict(request.headers) # Print request headers before sending print("Request Headers:") for header, value in signed_headers.items(): print(f"{header}: {value}") try: # Send POST request with signed headers response = requests.post( cloudfront_url, data=body, headers=signed_headers ) # Print response status and content print(f"\nStatus code: {response.status_code}") print("Response:", response.text) # Print response headers print("\nResponse Headers:") for header, value in response.headers.items(): print(f"{header}: {value}") except requests.exceptions.RequestException as e: print(f"An error occurred: {e}") # Usage cloudfront_url = "https://d111111abcdef8.cloudfront.net" file_path = r"filepath" region = "us-east-1" # example: "us-west-2" upload_file_to_lambda(cloudfront_url, file_path, region)