Как я могу заставить скрипт boto3 работать как лямбда-функция? - PullRequest
0 голосов
/ 04 декабря 2018

Это работает из 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 в доступныхи отправьте сообщение SNS в тему группы adm.Заранее спасибо!

Ответы [ 3 ]

0 голосов
/ 04 декабря 2018

Вам нужно связать роль IAM с Lambda, для которой необходимы разрешения.Справочные документы: https://docs.aws.amazon.com/lambda/latest/dg/intro-permission-model.html#lambda-intro-execution-role

0 голосов
/ 05 декабря 2018

Мне удалось заставить мой оригинальный код работать.

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'
        )

Спасибо за ваше время и комментарии.

0 голосов
/ 04 декабря 2018

Для любого доступа к ресурсам в AWS через любой поддерживаемый метод требуется, чтобы запрос был аутентифицирован.Если у вас локально настроен интерфейс командной строки AWS, 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_handler.

...