本文介绍了如何从python向Sync发送GraphQL查询?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们如何使用boto通过AWS AppSync发布GraphQL请求?

How do we post a GraphQL request through AWS AppSync using boto?

最终,我试图模仿一个移动应用程序,但该应用程序使用python访问AWS上的无堆栈/云信息堆栈.不是JavaScript也不是放大.

Ultimately I'm trying to mimic a mobile app accessing our stackless/cloudformation stack on AWS, but with python. Not javascript or amplify.

主要的痛点是身份验证;我已经尝试了十二种不同的方法.这是当前的消息,它生成一个带有"UnauthorizedException"和权限被拒绝"的"401"响应,考虑到我收到的其他一些消息,这实际上是相当不错的.我现在正在使用"aws_requests_auth"库来执行签名部分.我假设它使用本地环境中存储的/.aws/credentials对我进行身份验证,还是对?

The primary pain point is authentication; I've tried a dozen different ways already. This the current one, which generates a "401" response with "UnauthorizedException" and "Permission denied", which is actually pretty good considering some of the other messages I've had. I'm now using the 'aws_requests_auth' library to do the signing part. I assume it authenticates me using the stored /.aws/credentials from my local environment, or does it?

对于在哪里以及如何将认知身份和集合纳入其中,我有些困惑.例如:说我想模仿注册顺序?

I'm a little confused as to where and how cognito identities and pools will come into it. eg: say I wanted to mimic the sign-up sequence?

无论如何,代码看起来都非常简单;我只是不认可认证.

Anyways the code looks pretty straightforward; I just don't grok the authentication.

from aws_requests_auth.boto_utils import BotoAWSRequestsAuth

APPSYNC_API_KEY = 'inAppsyncSettings'
APPSYNC_API_ENDPOINT_URL = 'https://aaaaaaaaaaaavzbke.appsync-api.ap-southeast-2.amazonaws.com/graphql'

headers = {
    'Content-Type': "application/graphql",
    'x-api-key': APPSYNC_API_KEY,
    'cache-control': "no-cache",
}
query = """{
    GetUserSettingsByEmail(email: "john@washere"){
      items {name, identity_id, invite_code}
    }
}"""


def test_stuff():
    # Use the library to generate auth headers.
    auth = BotoAWSRequestsAuth(
        aws_host='aaaaaaaaaaaavzbke.appsync-api.ap-southeast-2.amazonaws.com',
        aws_region='ap-southeast-2',
        aws_service='appsync')

    # Create an http graphql request.
    response = requests.post(
        APPSYNC_API_ENDPOINT_URL, 
        json={'query': query}, 
        auth=auth, 
        headers=headers)

    print(response)

# this didn't work:
#    response = requests.post(APPSYNC_API_ENDPOINT_URL, data=json.dumps({'query': query}), auth=auth, headers=headers)

收益

{
  "errors" : [ {
    "errorType" : "UnauthorizedException",
    "message" : "Permission denied"
  } ]
}

推荐答案

这很简单-只要您知道.有一些我不感激的事情:

It's quite simple--once you know. There are some things I didn't appreciate:

  1. 我已经进行过IAM身份验证
    appsync有多种方式来处理身份验证.我们正在使用IAM,所以这就是我需要处理的,您的可能会有所不同.

  1. I've assumed IAM authentication
    There are a number of ways for appsync to handle authentication. We're using IAM so that's what I need to deal with, yours might be different.

Boto没有加入其中.
我们希望像任何常规下注者一样发出请求,他们不使用boto,我们也不这样做.拖曳AWS Boto文档是浪费时间.

Boto doesn't come into it.
We want to issue a request like any regular punter, they don't use boto, and neither do we. Trawling the AWS boto docs was a waste of time.

使用 AWS4Auth
我们将向aws发送常规 http请求,因此,尽管我们可以使用python 请求,但它们需要通过附加标头进行身份验证.而且,当然,AWS auth标头是特殊的,并且与所有其他标头不同.您可以尝试找出方法您自己,或者您可以寻找已经做过的其他人: Aws_requests_auth ,我刚开始使用的它可能效果很好,但是我最终得到了 AWS4Auth .还有许多其他价值可疑的东西.没有得到亚马逊认可或提供的(我可以找到).

Use the AWS4Auth library
We are going to send a regular http request to aws, so whilst we can use python requests they need to be authenticated--by attaching headers. And, of course, AWS auth headers are special and different from all others.You can try to work out how to do ityourself, or you can go looking for someone else who has already done it: Aws_requests_auth, the one I started with, probably works just fine, but I have ended up with AWS4Auth. There are many others of dubious value; none endorsed or provided by Amazon (that I could find).

appsync指定为服务"
我们在叫什么服务?我没有发现任何人在任何地方进行此操作的示例.所有的例子都是琐碎的S3或EC2甚至是EB,这些都留下了不确定性.我们应该和api-gateway服务进行对话吗?此外,您将此详细信息输入AWS4Auth例程或身份验证数据.显然,事后看来,该请求到达了Appsync,因此它将由Appsync进行身份验证,因此在将auth标头放在一起时,将"appsync"指定为 service .

Specify appsync as the "service"
What service are we calling? I didn't find any examples of anyone doing this anywhere. All the examples are trivial S3 or EC2 or even EB which left uncertainty. Should we be talking to api-gateway service? Whatsmore, you feed this detail into the AWS4Auth routine, or authentication data. Obviously, in hindsight, the request is hitting Appsync, so it will be authenticated by Appsync, so specify "appsync" as the service when putting together the auth headers.

它作为:

import requests
from requests_aws4auth import AWS4Auth

# Use AWS4Auth to sign a requests session
session = requests.Session()
session.auth = AWS4Auth(
    # An AWS 'ACCESS KEY' associated with an IAM user.
    'AKxxxxxxxxxxxxxxx2A',
    # The 'secret' that goes with the above access key.                    
    'kwWxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxgEm',    
    # The region you want to access.
    'ap-southeast-2',
    # The service you want to access.
    'appsync'
)
# As found in AWS Appsync under Settings for your endpoint.
APPSYNC_API_ENDPOINT_URL = 'https://nqxxxxxxxxxxxxxxxxxxxke'
                           '.appsync-api.ap-southeast-2.amazonaws.com/graphql'
# Use JSON format string for the query. It does not need reformatting.
query = """
    query foo {
        GetUserSettings (
           identity_id: "ap-southeast-2:8xxxxxxb-7xx4-4xx4-8xx0-exxxxxxx2"
        ){ 
           user_name, email, whatever 
}}"""
# Now we can simply post the request...
response = session.request(
    url=APPSYNC_API_ENDPOINT_URL,
    method='POST',
    json={'query': query}
)
print(response.text)

哪个产量

# Your answer comes as a JSON formatted string in the text attribute, under data. 
{"data":{"GetUserSettings":{"user_name":"0xxxxxxx3-9102-42f0-9874-1xxxxx7dxxx5"}}}

获取凭据

要摆脱硬编码的密钥/秘密,您可以使用本地AWS ~/.aws/config~/.aws/credentials,并且可以通过这种方式完成...

Getting credentials

To get rid of the hardcoded key/secret you can consume the local AWS ~/.aws/config and ~/.aws/credentials, and it is done this way...

# Use AWS4Auth to sign a requests session
session = requests.Session()
credentials = boto3.session.Session().get_credentials()
session.auth = AWS4Auth(
    credentials.access_key,
    credentials.secret_key,
    boto3.session.Session().region_name,
    'appsync',
    session_token=credentials.token
)
...<as above>

这似乎尊重环境变量AWS_PROFILE承担的不同角色.

This does seem to respect the environment variable AWS_PROFILE for assuming different roles.

请注意, STS .get_session_token 并非做到这一点,因为它可能尝试从某个角色中扮演一个角色,具体取决于它的关键字与AWS_PROFILE值匹配的位置. credentials文件中的标签将起作用,因为这些键就在其中,但是config文件中找到的名称却不起作用,因为这已经假定了角色.

Note that STS.get_session_token is not the way to do it, as it may try to assume a role from a role, depending where it keyword matched the AWS_PROFILE value. Labels in the credentials file will work because the keys are right there, but names found in the config file do not work, as that assumes a role already.

这篇关于如何从python向Sync发送GraphQL查询?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-28 03:52