利用AWS IAM签名

在使用内部微服务时,通常可以为各种目的识别呼叫服务,例如利用审核,速率限制和基本授权是有用的。传统上,这是通过向客户服务发出API键来执行,以及/或需要额外的HTTP查询参数或标识客户端的标题。 这两种方法都不可靠,并且在API键可以成为持续的维护头痛。在这篇文章中,我们讨论了一种利用AWS IAM认证的方法,只需要AWS SDK,而无需任何其他库或基础架构。

一个桌子上的咖啡杯,带有'hello我的名字是'贴纸旁边的贴纸
拍摄者艾莉丝uns

最近这个话题又来了,我们很好奇拱顶实现了基于角色的身份验证,无需额外的基础架构或管理来支持,除非将角色分配给Vault中的标识。 调查揭示了一个进程的信息描述以及一些示例源代码这展示了执行的具体步骤。这种方法的关键组成部分是AWS. STS服务这为源自任何AWS帐户的任何签名请求提供签名验证。

请求签名

使用AWS API for nodejs,创建了一个简单的概念证明,它使用相同的方法来捕获请求签名:

const AWS = require('aws-sdk');
 
const HEADER_KEYS = ["authorization", "x-amz-security-token", "x-amz-date", "x-amz-content-sha256"];

const sts = new AWS.STS();
const awsRequest = sts.getCallerIdentity();

let headers = {};

awsRequest.on('send', () => {
  let awsHeaders = awsRequest.httpRequest.headers;
  let awsHeaderKeys = Object.keys(awsHeaders);

  for (headerKey of HEADER_KEYS) {
    let awsHeaderKey = awsHeaderKeys.find((header) => header.toLowerCase() === headerKey);
    headers[headerKey] = awsRequest.httpRequest.headers[awsHeaderKey];
  }
});

awsRequest.send((err, data) => {
  console.log('headers: ', headers);
});

在环境中使用有效的AWS凭据运行上面的代码后,控制台中的输出将显示签名标题,特别是“授权”,“X-AMZ-Security-token”,“X-AMZ-DATE”和“X-AMZ-Content-SHA256”。 由于该请求仅作为指示AWS SDK计算和添加符号标题的手段,因此丢弃响应。 如果有更直接的方式生成签名标题,但就像这种写作一样,那就更好地是最方便的机制。

为了将凭据发送到另一个服务进行验证,将标题简单地复制到目标服务的请求中:

for (const header of HEADER_KEYS) {
  request.headers[header] = signedHeaders.get(header);
}

以前代码块中的签名标题被添加到名为signedheaders的地图中

验证签名

在接收服务中,使用由调用服务提供的标头对AWS STS服务进行呼叫:

import * as rp from "request-promise";
const HEADER_KEYS = ["authorization", "x-amz-security-token", "x-amz-date", "x-amz-content-sha256"];
const AWS_STS = "//sts.amazonaws.com";
let headers: any = {};
// requestHeaders represents the incoming request's headers from Express, Hapi, etc.
for (const header of HEADER_KEYS) {
  headers[header] = requestHeaders[header];
}
headers["Accept"] = "application/json,text/plain";
let response = await rp.post(AWS_STS, {
  form: { Action: "GetCallerIdentity", Version: "2011-06-15" },
  headers: headers,
});

let parsedResponse = JSON.parse(response);

生成的响应将包括以下属性:

  • respectemetadata.–包含ConserentId.
  • UserID:AWS用户ID令牌
  • 帐户:签名发起的AWS帐号
  • ARN:用于签署请求的IAM角色的资源标识符

对于大多数目的,IAM角色的ARN是捕获请求服务的身份的理想选择,因为它包含可以轻松解释出来的简单角色名称。

缓存考虑因素

这种方法的一个明显的问题是它为请求和响应添加了延迟。 这可以通过在每侧结合基本缓存来减轻这一点: 

  • 在请求者方面,每10分钟可以在后台再生签名,因为签名有效15分钟默认情况下.  
  • 在接收服务中,一旦验证了签名,就可以在接下来的15分钟内收到完全相同的签名时缓存。  

安全考虑因素

虽然目标用例是用于内部系统识别的,但应该指出这种方法容易受到中间人攻击的影响,这将使攻击者能够使用符号标题来模拟原始服务。 有一些处理这种情况的机制将在未来的文章中涵盖。

概括

通过利用AWS IAM认证,服务可以可靠地呈现他们的凭据和接收服务可以验证那些使用AWS的凭据。 由于我们大多数服务已经为其他目的使用了AWS SDK,因此完成此目的需要额外的库或基础架构。

发表评论

您的电子邮件地址不会被公开。必需的地方已做标记*