如何在同一个 lambda 函数中使用 4 个不同的 http_methods?

问题描述 投票:0回答:1

我有这个函数,我打算用它来处理 ec2 的实例,用 get 列出该区域中的所有实例,post 来创建一个新实例,put 来修改一个实例,delete 来删除一个实例,我正在使用 python 3.9 lambda 和无服务器

import json
import boto3

def ec2_crud(event, context):
    http_method = event['httpMethod']
    try:
        # Crear una conexión con EC2 usando la región en la que se encuentra la función Lambda
        region = context.invoked_function_arn.split(":")[3]
        ec2 = boto3.resource('ec2', region_name=region)

        if http_method == 'GET':
            # Obtener todas las instancias de EC2 en la región
            instances = ec2.instances.all()

            instance_list = []
            for instance in instances:
                instance_info = {
                    'InstanceId': instance.id,
                    'InstanceType': instance.instance_type,
                    'State': instance.state['Name']
                }
                instance_list.append(instance_info)

            return {
                'statusCode': 200,
                'body': json.dumps(instance_list)
            }
        elif http_method == 'POST':
      
            try:
               
                request_data = json.loads(event['body'])
                instance_name = request_data['name']
                instance_size = request_data['size']
                instance_keys = request_data['keys']

                ec2_client = boto3.client('ec2')
                new_instance = ec2_client.run_instances(
                    ImageId='ami-03f65b8614a860c29',  # Reemplaza con la AMI que desees usar
                    InstanceType=instance_size,
                    KeyName=instance_keys,
                    MinCount=1,
                    MaxCount=1
                )['Instances'][0]

                ec2_client.create_tags(Resources=[new_instance['InstanceId']], Tags=[{'Key': 'Name', 'Value': instance_name}])

                return {
                    'statusCode': 200,
                    'body': json.dumps({'message': 'Nueva instancia creada con éxito.', 'InstanceId': new_instance['InstanceId']})
                }
            except Exception as e:
                return {
                    'statusCode': 500,
                    'body': json.dumps({'error': str(e)})
                }
        elif http_method == 'PUT':
            # Implementar la lógica para actualizar una instancia de EC2
            instance_id = event['pathParameters']['instance_id']
            instance_size = json.loads(event['body'])['size']
            instance_name = json.loads(event['body'])['name']

            # Crear una conexión con el servicio EC2
            ec2_client = boto3.client('ec2')

            try:
                # Actualizar el tamaño y el nombre de la instancia
                ec2_client.modify_instance_attribute(InstanceId=instance_id, Attribute='instanceType', Value=instance_size)
                ec2_client.create_tags(Resources=[instance_id], Tags=[{'Key': 'Name', 'Value': instance_name}])

                return {
                    'statusCode': 200,
                    'body': json.dumps({'message': f'Instancia {instance_id} actualizada con éxito.'})
                }

            except Exception as e:
                return {
                    'statusCode': 500,
                    'body': json.dumps({'error': str(e)})
                }
        elif http_method == 'DELETE':
            # Implementar la lógica para eliminar una instancia de EC2
            instance_id = event['pathParameters']['instance_id']

            # Crear una conexión con el servicio EC2
            ec2_client = boto3.client('ec2')

            try:
                # Eliminar la instancia
                ec2_client.terminate_instances(InstanceIds=[instance_id])

                return {
                    'statusCode': 200,
                    'body': json.dumps({'message': f'Instancia {instance_id} eliminada con éxito.'})
                }

            except Exception as e:
                return {
                    'statusCode': 500,
                    'body': json.dumps({'error': str(e)})
                }
        else:
            return {
                'statusCode': 400,
                'body': json.dumps({'error': 'Método HTTP inválido.'})
            }
    except Exception as e:
        return {
            'statusCode': 500,
            'body': json.dumps({'error': str(e)})
        }

当我使用curl测试get和post块时效果很好并运行任务,但是当我尝试使用put和delete时会出现此错误{“message”:“缺少身份验证令牌”}并且不知道为什么?

我尝试修改和删除ec2实例

python-3.x aws-lambda serverless-framework
1个回答
0
投票

错误消息“缺少身份验证令牌”表明您尝试在未经正确身份验证的情况下访问 AWS 资源。这可能是由于您的 AWS Lambda 函数配置为访问 EC2 实例并修改/删除它们的方式所致。

当您请求修改或删除 EC2 实例时,您需要确保您的 Lambda 函数具有执行这些操作所需的权限。

boto3
库使用 Lambda 函数可用的 AWS 凭证来验证这些请求。

您可以采取以下几个步骤来排查和解决问题:

  1. IAM 角色权限:确保分配给您的 Lambda 函数的 IAM 角色具有修改和删除 EC2 实例的必要权限。该角色应附加适当的策略,例如

    AmazonEC2FullAccess
    或授予所需权限的自定义策略。

  2. 环境变量:检查您是否已为 Lambda 函数配置必要的 AWS 环境变量。这些变量包括

    AWS_ACCESS_KEY_ID
    AWS_SECRET_ACCESS_KEY
    。但是,建议对 Lambda 函数使用 IAM 角色,而不是硬编码凭证。

  3. 凭证链:如果将函数配置为使用 IAM 角色,则 Lambda 函数可以自动从 IAM 角色获取凭证。在本地运行时(出于测试目的),您应确保 AWS CLI 配置了必要的凭证 (

    aws configure
    )。

  4. 调用权限:如果您使用 API Gateway 触发 Lambda 函数,请确保 API Gateway 具有调用 Lambda 函数所需的 IAM 权限。这对于

    PUT
    DELETE
    等方法尤其重要。

  5. 端点配置:确保您的 Lambda 函数部署在正确的区域中,并且您尝试修改或删除的 EC2 实例也在同一区域中。

  6. VPC 配置:如果您的 Lambda 函数配置为在 VPC 中运行,您可能需要配置 VPC 和安全组以允许 Lambda 函数进行出站互联网访问。

请记住,Lambda 函数执行上下文可能会影响凭证和网络访问的可用性。使用

curl
进行本地测试可能无法完全模拟 Lambda 函数运行的环境。

此外,我注意到您正在使用

context.invoked_function_arn
来确定区域。虽然这可行,但确定区域的更可靠、更直接的方法是使用
boto3
的内置
session
对象:

import boto3

def ec2_crud(event, context):
    region = boto3.Session().region_name
    # ... rest of your code ...

请务必彻底检查您的 AWS IAM 设置、Lambda 配置以及测试 Lambda 函数的环境,以确保它具有必要的权限和资源来对 EC2 实例执行所需的操作。

© www.soinside.com 2019 - 2024. All rights reserved.