如何将签名的 HTTP 请求从 AWS Lambda 发送到 AppSync GraphQL?

Posted

技术标签:

【中文标题】如何将签名的 HTTP 请求从 AWS Lambda 发送到 AppSync GraphQL?【英文标题】:How to send signed HTTP request from AWS Lambda to AppSync GraphQL? 【发布时间】:2019-11-19 00:34:43 【问题描述】:

我不确定如何在 AppSync GraphQL 端点上发送签名的 http 请求。 AWS 中没有用于执行此操作的库。

aws-amplify 不起作用,因为仅适用于浏览器,不适用于 Lambda 函数。 aws-sdk AppSync 仅供管理员使用,没有调用用户端api的方法

可以从 AWS Lambda 发出 IAM 签名的 HTTP 请求吗? (以某种简单的方式)

【问题讨论】:

【参考方案1】:

我会推荐阅读这篇文章:Backend GraphQL: How to trigger an AWS AppSync mutation from AWS Lambda,

引用作者https://***.com/users/1313441/adrian-hall,我们已经:

GraphQL 通过 HTTPS 进行路由。这意味着我们可以使用简单的 HTTPS POST 来模拟 GraphQL 客户端库。由于我们使用的是 IAM,因此我们需要在交付请求之前对其进行签名。这是我的代码:

// ... more code here
    // POST the GraphQL mutation to AWS AppSync using a signed connection
    const uri = URL.parse(env.GRAPHQL_API);
    const httpRequest = new AWS.HttpRequest(uri.href, env.REGION);
    httpRequest.headers.host = uri.host;
    httpRequest.headers['Content-Type'] = 'application/json';
    httpRequest.method = 'POST';
    httpRequest.body = JSON.stringify(post_body);

    AWS.config.credentials.get(err => 
        const signer = new AWS.Signers.V4(httpRequest, "appsync", true);
        signer.addAuthorization(AWS.config.credentials, AWS.util.date.getDate());

        const options = 
            method: httpRequest.method,
            body: httpRequest.body,
            headers: httpRequest.headers
        ;

        fetch(uri.href, options)
// ... more code here

我一直将它用作我所有 Lambda->AppSync 通信的模板!

【讨论】:

更新链接Backend GraphQL: How to trigger an AWS AppSync mutation from AWS Lambda【参考方案2】:

您可以使用任何 graphql 客户端或 sigv4 签名的 HTTP 请求。以下是您为请求创建签名的方法 (https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html)。如果您将执行角色附加到您的 lambda,您可以从 lambda 环境变量 (https://docs.aws.amazon.com/lambda/latest/dg/lambda-environment-variables.html) 访问它的访问密钥。

【讨论】:

【参考方案3】:

这个问题已经回答了,但是因为我首先提出了这个问题,所以我想我会分享另一个解决方案。

我的用例是向 AWS 上托管的自定义 HTTP API 发送签名请求,其中 cognito 用作身份验证后端,仅启用了 ALLOW_USER_SRP_AUTH(因此没有 ALLOW_ADMIN_USER_PASSWORD_AUTH 或 ALLOW_USER_PASSWORD_AUTH)

我最终结合了 AWS 中的这个示例,展示了如何在节点中进行 cognito 身份验证:

https://www.npmjs.com/package/amazon-cognito-identity-js(用例 4)

AWS 的另一个例子展示了如何签署请求:

https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-request-signing.html#es-request-signing-node

您通过替换这一行(来自第一个示例)将第二个示例插入到第一个示例中:

//(...)
        //refreshes credentials using AWS.CognitoIdentity.getCredentialsForIdentity()
        AWS.config.credentials.refresh(error => 
            if (error) 
                console.error(error);
             else 
                // Instantiate aws sdk service objects now that the credentials have been updated.
                // example: var s3 = new AWS.S3();
                console.log('Successfully logged!'); // <-- replace this line
            
        );
//(...)

第二个示例需要进行一些调整以满足您的要求,我必须更改的是:

HTTP 方法(我需要 GET) signer 声明 - 我不得不更改服务(将 es 替换为 execute-api) 在signer.addAuthorization 中,我不得不使用AWS.config.credentials(已经由第一个示例中的代码初始化)而不是AWS.EnvironmentCredentials('AWS')

希望这对某人有所帮助!

【讨论】:

以上是关于如何将签名的 HTTP 请求从 AWS Lambda 发送到 AppSync GraphQL?的主要内容,如果未能解决你的问题,请参考以下文章

AWS S3 通过预签名 URL 上传返回 400 错误请求

AWS S3 - 我们计算的请求签名与您提供的签名不匹配。检查您的密钥和签名方法

如何使用 AWS 流式传输上传的视频?

从 .Net 应用程序到 AWS API Gateway 的 HTTP POST 请求未按预期工作

带有签名 cookie 的 AWS Cloudfront POST 请求

如何将自签名证书分配给 AWS 弹性 beantalk 应用程序