【问题标题】:How can I get boto3 script to run as a Lambda function?如何让 boto3 脚本作为 Lambda 函数运行?
【发布时间】:2019-05-05 07:25:21
【问题描述】:

这适用于 CLI,但不适用于 AWS Lambda:

#This will list out all volumes that aren't in use or attached to instances
import boto3
import sys

ec2 = boto3.resource('ec2')
client = boto3.client('sns')
vol_array = ec2.volumes.all()
vol_avail = []

#def chk_vols(event, context):
for v in vol_array:
    if v.state == 'available':
        vol_avail.append(v.id)

response = client.publish(
    TopicArn='arn:aws:sns:us-east-1:444444444444:adm-group',
    Message=str(vol_avail),
    Subject='AWS Volumes Available'
)

我想将此代码转换为 AWS Lambda 函数。我已取消注释该行: #def chk_vols(事件,上下文): 并正确地将 For 循环移到 'def' 语句下方。

此代码将检查是否有任何 AWS 卷处于可用状态,并向 adm-group 主题发送 SNS 消息。提前谢谢!

【问题讨论】:

  • 您的问题是与权限有关还是仅与如何编写和配置 Lambda 函数处理程序本身有关?

标签: python-3.x amazon-web-services aws-lambda boto3


【解决方案1】:

对于通过任何支持的方法访问 AWS 的任何资源都需要对请求进行身份验证。如果您在本地配置了 AWS CLI,boto3 知道如何使用这些凭证进行身份验证,因此您可以访问资源并修改它们。

很遗憾,Lambda 不支持凭证,因为您需要考虑其他方式。最安全的方法是使用STS 担任角色并获取临时凭据。

    try:
        sts_client = boto3.client('sts')

        assumedRoleObject = sts_client.assume_role(
            RoleArn="arn:aws:iam::" + "AwsAccountNumber" + ":role/" + "RoleWithSTSPermissions",
            RoleSessionName="NameOfTheSession"
        )

        credentials = assumedRoleObject['Credentials']

        _client = boto3.client(
            'ec2',
            aws_access_key_id=credentials['AccessKeyId'],
            aws_secret_access_key=credentials['SecretAccessKey'],
            aws_session_token=credentials['SessionToken'],
            region_name=_region
        )
    except Exception as e:
        print(e.message)
        raise

如果这些东西是变量是理想的,这样您就可以根据需要动态更改它们。

例子

import os
import boto3
import logging

AwsAccount = dict(
    number=None,
    role=None,
    region=None
)
def authenticate(_region, _resource):
    try:
        sts_client = boto3.client('sts')

        assumedRoleObject = sts_client.assume_role(
            RoleArn="arn:aws:iam::" + AwsAccount['number'] + ":role/" + AwsAccount['role'],
            RoleSessionName="LambdaAssumeRoleSession"
        )

        credentials = assumedRoleObject['Credentials']

        _client = boto3.client(
            _resource,
            aws_access_key_id=credentials['AccessKeyId'],
            aws_secret_access_key=credentials['SecretAccessKey'],
            aws_session_token=credentials['SessionToken'],
            region_name=_region
        )
    except Exception as e:
        log.warn(e.message)
        log.warn("Switching to local credentials")

        try:
            # TODO: Remove failover profile in production
            _session = boto3.session.Session(region_name=_region)
            _client = _session.client(_resource, region_name=_region)
            log.info("Successfully authenticated using local credentials")
        except Exception as e:
            log.error(e.message)
            raise

    return _client

def main():
    _client = authenticate(AwsAccount['region'], 'ec2')

    return

def lambda_handler(event, context):
    try:
        AwsAccount['number'] = os.environ['AWS_ACCOUNT'].strip()
        AwsAccount['region'] = os.environ['AWS_REGION'].strip()
        AwsAccount['role'] = os.environ['AWS_LAMBDA_ROLE'].strip()
    except Exception as e:
        log.error(e)
        raise

    main()

    return

if __name__ == '__main__':
    lambda_handler(None, None)

如果您已在本地和 Lambda 上配置环境变量,则可以在本地和 Lambda 上测试此代码

当您创建 Lambda 函数时,请确保将 lambda_handler 定义为处理程序。

【讨论】:

  • Lambda 确实通过 IAM 角色支持 IAM 权限,这些角色可以分配给 Lambda。虽然这个建议在安全方面还不错,但说 Lambda 不支持 IAM 是不准确的。
  • @JamesG 我不是说 Lambda 不支持 IAM 角色,我是说它不像 CLI 那样支持凭证。对于我的回答,无论如何它确实需要角色才能工作。很抱歉,如果我造成任何混乱。
  • 感谢您的 cmets 和代码示例。我从命令提示符 (CLI) 成功运行了 Python 3.7 脚本。我确实使用带有配置文件的凭证/配置文件安装和配置了 AWS CLI。 Lambda 函数正在使用的 IAM 角色添加了以下权限:AdministrativeAcess AWSLambdaBasicExecutionRole AWSLambdaVPCAccessExecutionRole AmazonSNSFullAccess 我从 AWSLambdaBasicExecutionRole 开始并添加了其他“测试”。
  • 这按预期工作,但我正在努力确定所需的确切访问权限。 # This will list out all volumes that aren't in use or attached to instances import boto3 import sys def chk_vols(event, context): ec2 = boto3.resource('ec2') client = boto3.client('sns') vol_array = ec2.volumes.all() vol_avail = [] for v in vol_array: if v.state == 'available': vol_avail.append(v.id) response = client.publish( TopicArn='arn:aws:sns:us-east-1:444444444444:ep-adm-grp', Message=str(vol_avail), Subject='AWS Volumes Available' )
  • 我发现最简单的方法是使用IAM 中的Create policy 向导。它允许沙箱,因此您可以测试实际的策略。 docs.aws.amazon.com/IAM/latest/UserGuide/…
【解决方案2】:

您需要将 IAM 角色与具有所需权限的 Lambda 相关联。参考文档:https://docs.aws.amazon.com/lambda/latest/dg/intro-permission-model.html#lambda-intro-execution-role

【讨论】:

  • 这个答案是准确的,但是好的 SO 答案提供的细节不仅仅是一个链接。您能否详细说明附加 IAM 角色所需的一些步骤?我会这样做,但你应该得到这个公认的答案。
【解决方案3】:

我能够让我的原始代码工作。

import boto3

ec2 = boto3.resource('ec2')
sns = boto3.client('sns')

def chk_vols(event, context):
    vol_array = ec2.volumes.all()
    vol_avail = []

    for v in vol_array:
        if v.state == 'available':
            vol_avail.append(v.id)

    if vol_avail:
        sns.publish(
            TopicArn='arn:aws:sns:us-east-1:444444444444:adm-group',
            Message=str(vol_avail),
            Subject='AWS Volumes Available'
        )

感谢您的时间和 cmets。

【讨论】:

    猜你喜欢
    • 2021-12-03
    • 2019-06-11
    • 1970-01-01
    • 2019-09-19
    • 2021-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-24
    相关资源
    最近更新 更多