1

私は最近How to allow invoking an AWS Lambda function only from EC2 instances inside a VPCについて質問を投稿しました。 "AWSラムダロール"ポリシーを持つIAMロールをEC2インスタンスに添付することでそれを稼働させることができました。これで、boto3を使用してラムダ関数を呼び出すことができます。Python asyncioでEC2インスタンスからAWS Lambda関数を呼び出す方法

ここで、asyncio await構文を使用して、ラムダ関数を非同期に呼び出したいと思います。ラムダ関数はInvokeType='Event'を設定して非同期バージョンを提供していますが、実際には関数の結果を得ることなく呼び出しを即座に返します。

この関数には時間がかかるので、私は多くの関数を同時に起動したいと思いますが、関数が戻るのを待っている間に実行をブロックしないようにしたいと思います。

私はaiobotocoreを使用しようとしましたが、これは基本的な 's3'サービス機能のみをサポートしています。

これを解決する最善の方法は、AWS APIゲートウェイサービスを使用して、aiohttpを使用して簡単に処理できるGET/POSTリクエストを介してラムダ関数を呼び出すことです。

しかし、私はそれを動作させることはできません。

import requests 
r = requests.get('https://url_to_api_gateway_for_function') 

私が禁止応答<Response [403]>を得る:

私はEC2 IAMロールにポリシー「AmazonAPIGatewayInvokeFullAccess」が、私はしようとするたびに追加しました。

ラムダ関数でトリガを直接使用してAPIゲートウェイを作成しました。

また、APIパス設定にポストメソッドを追加して、 "AWS_IAM"認証を設定し、それを "prod"デプロイメントとしてデプロイするようにしました。それと同じ禁止された応答。私はそれを "APIゲートウェイのテスト画面でテストすると、うまくいきます"。

これを修正する方法はありますか?私はいくつかのステップを欠いていますか?

+0

http://docs.aws.amazon.com/apigateway/latest/developerguide/getting-started.html#getting-started-prerequisites 'あなたが使用したり、管理ポリシーをカスタマイズすることができますAWSLambdaFullAccess(arn:aws:iam :: aws:policy/AWSLambdaFullAccess)を添付してIAMユーザーに添付してください。 – mootmoot

+0

このチュートリアルを試しましたが、** AWS_IAM **をAPI ... EC2からそれをオンにするとすぐに、私はEC2インスタンスのポリシーAWSLambdaFullAccessを使用していましたが、403レスポンスを取得します... – Bertone

+0

AWS_IAM認可とは何ですか? – mootmoot

答えて

2

私はいくつかの苦労の後に私の問題を解決することができました。

問題は、pythonのリクエストのようなcurlとpythonモジュールは、実行中のEC2マシンのIAM認証情報でhttpリクエストに署名しないということです。 AWS GATEWAY APIへのHTTPリクエストは、AWS v4サインインプロトコルを使用して署名する必要があります。

例はここにある: 幸いにもhttp://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html

、物事をシンプルに保つために、要求-AWS-記号のようないくつかのヘルパーモジュールがあります https://github.com/jmenga/requests-aws-sign

終わりにコードのようなものを見ることができます。

import aiohttp 
import asyncio 
from requests_aws_sign import AWSV4Sign 
from boto3 import session 

session = session.Session() 
credentials = session.get_credentials() 
region = session.region_name or 'ap-southeast-2' 
service = 'execute-api' 
url = "get_it_from_api->stages->your_deployment->invoke_url" 
auth=AWSV4Sign(credentials, region, service) 

async def invoke_func(loop): 
    async with aiohttp.request('GET', url, auth=auth, loop=loop) as resp: 
     html = await resp.text() 
     print(html) 

loop = asyncio.get_event_loop() 
loop.run_until_complete(main(loop)) 

希望すると、他の誰かに時間を節約できます。

EDIT:完全を期すために

と私は上記のコードが原因requests_aws_signがaiohttpと互換性がないという事実のために動作しないことを言っている他人を助けます。私はいくつかの "認証フィールドのエラー"を取得していた。

私が使用してそれを解決するためにうまく管理:

async with session.get(url, headers=update_headers()) as resp: 
私はその後、使用上の要求にそれらを直接設定することができるようにupdate_headers()は模倣がヘッダに何requests_aws_signをしていた単純な関数(ある

ヘッダパラメータ)。 それは次のようになります。

def update_headers(sim_id): 
    url = urlparse("get_it_from_api->stages->your_deployment->invoke_url") 
    path = url.path or '/' 
    querystring = '' 
    if url.query: 
     querystring = '?' + urlencode(parse_qs(url.query), doseq=True) 
    safe_url = url.scheme + '://' + url.netloc.split(':')[0] + path + querystring 
    request = AWSRequest(method='GET', url=safe_url) 
    SigV4Auth(credentials, service, region).add_auth(request) 
    return dict(request.headers.items()) 
関連する問題