在Python中向AWS Elasticsearch发出签名的HTTP请求

时间:2016-07-01 11:26:53

标签: python-2.7 amazon-web-services elasticsearch boto3

我正在尝试制作一个简单的Python Lambda,它可以为我们的Elasticsearch数据库创建快照。这是通过Elasticsearch's REST API使用简单的HTTP请求完成的。

但是,对于AWS,我必须签署这些请求。我有一种感觉,它可以通过boto3的低级客户端来实现,可能是generate_presigned_url,但我不能在我的生活中找出如何正确调用此函数。例如,有效的ClientMethod是什么?我试过ESHttpGet,但无济于事。

有人能指出我正确的方向吗?

5 个答案:

答案 0 :(得分:9)

我挣扎了一段时间做类似的事情。目前,boto3库并不支持发出已签名的es请求,但由于我raised an issue与它们一起成为了一个功能请求。

以下是我在此期间使用上面提到的DavidMuller's library和boto3获取我的STS会话凭据所做的事情:

import boto3
from aws_requests_auth.aws_auth import AWSRequestsAuth
from elasticsearch import Elasticsearch, RequestsHttpConnection

session = boto3.session.Session()
credentials = session.get_credentials().get_frozen_credentials()

es_host = 'search-my-es-domain.eu-west-1.es.amazonaws.com'
awsauth = AWSRequestsAuth(
    aws_access_key=credentials.access_key,
    aws_secret_access_key=credentials.secret_key,
    aws_token=credentials.token,
    aws_host=es_host,
    aws_region=session.region_name,
    aws_service='es'
)

# use the requests connection_class and pass in our custom auth class
es = Elasticsearch(
    hosts=[{'host': es_host, 'port': 443}],
    http_auth=awsauth,
    use_ssl=True,
    verify_certs=True,
    connection_class=RequestsHttpConnection
)

print(es.info())

希望这能节省一些时间。

答案 1 :(得分:7)

请求库有几个Python扩展,它们将为您执行SigV4签名。我使用了this one,效果很好。

答案 2 :(得分:3)

我最近发布了requests-aws-sign,它为Python请求库提供了AWS V4请求签名。

如果查看this code,您将看到如何使用Botocore生成V4请求签名。

答案 3 :(得分:1)

虽然其他答案都很好,但我想避免使用外部软件包。显然,botocore本身具有签署请求的所有必需功能,这只是查看源代码而已。这就是我最终直接发送AWS API请求的内容(出于演示目的,这些内容经过了硬编码):

  import boto3
  import botocore.credentials
  from botocore.awsrequest import AWSRequest
  from botocore.endpoint import BotocoreHTTPSession
  from botocore.auth import SigV4Auth

  params = '{"name": "hello"}'
  headers = {
    'Host': 'ram.ap-southeast-2.amazonaws.com',
  }
  request = AWSRequest(method="POST", url="https://ram.ap-southeast-2.amazonaws.com/createresourceshare", data=params, headers=headers)
  SigV4Auth(boto3.Session().get_credentials(), "ram", "ap-southeast-2").add_auth(request)    


  session = BotocoreHTTPSession()
  r = session.send(request.prepare())

答案 4 :(得分:0)

为什么不只使用请求?

import requests
headers = {'Content-Type': 'application/json',}
data = '{"director": "Burton, Tim", "genre": ["Comedy","Sci-Fi","R-rated"],"profit" : 98 , "year": 1996, "actor": ["Jack Nicholson","PierceBrosnan","Sarah Jessica Parker"], "title": "Mars Attacks!"}'
response = requests.post('https://search-your-awsendpoint.us-west-2.es.amazonaws.com/yourindex/_yourdoc/', headers=headers, data=data)

这对我有用