在API Gateway的Lambda中使用哪些凭证来访问其他AWS服务

时间:2018-11-19 05:42:41

标签: amazon-web-services aws-lambda amazon-cognito

我有一个使用Cognito用户池授权者的Cognito用户池和API网关。池中的每个用户都分配给具有IAM角色的组。借助此设置,客户端将通过Cognito进行身份验证,然后将ID令牌发送到API网关,API网关对请求进行授权并将其传递给Lambda函数。然后,lambda执行其他服务(DynamoDB和S3)。我的问题是我需要在lambda中使用哪些凭证?

一种选择是使用从API网关传递给lambda的ID令牌,以从STS获取临时凭证。基本上,这使我可以使用用户的组IAM角色来访问其他AWS资源,并且外观如下:

var credentials = new CognitoAWSCredentials(
    "us-east-1:...", // Identity pool ID
    RegionEndpoint.USEast1 // Region
);

credentials.AddLogin(
    "cognito-idp.us-east-1.amazonaws.com/us-east-...", // User pool ID
    "eyJraWQiOiJi..." // ID token
);

// use credentials to access AWS services

另一种选择是使用分配给Lambda函数的执行角色,但是几乎感觉这似乎更适合于其他方案……也许那些将lambda作为事件的一部分执行的方案?我似乎也不明白如何在lambda本身中获得这些凭据。

还有其他我想念的东西吗?在这里采取什么好方法?

更新

我上面提到的内容几乎是正确的,但并不完全正确。首先,确定您的用户是否需要未经授权的访问。如果是这样,请转到您的身份池并启用未经授权的访问。

要获取未授权用户的访问/秘密密钥,您可以执行以下操作(使用C#SDK,但以下概念适用于其他语言):

var client = new AmazonCognitoIdentityClient(
    new AnonymousAWSCredentials(), // We're making public API calls
    RegionEndpoint.USEast1); // Your Region

var identityId = await client.GetIdAsync(new GetIdRequest
{
    AccountId = "****", // AWS account ID
    IdentityPoolId = "us-east-1:****" // Identity Pool ID
});

var credentials = await client.GetCredentialsForIdentityAsync(new GetCredentialsForIdentityRequest()
{
    IdentityId = identityId.IdentityId
});

// Use credentials.Credentials when calling AWS services

以上内容将颁发凭据,该凭据具有由您的身份池中定义的未经身份验证的IAM角色定义的权限。

要获取经过身份验证的用户的凭据,请执行以下操作:

var client = new AmazonCognitoIdentityClient(
    new AnonymousAWSCredentials(), // We're making public API calls
    RegionEndpoint.USEast1); // Your region

var getIdentityIdRequest = new GetIdRequest
{
    AccountId = "****", // AWS Account ID
    IdentityPoolId = "us-east-1:****" // Identity Pool ID
};

getIdentityIdRequest.Logins.Add(
    "cognito-idp.us-east-1.amazonaws.com/us-east-1****", // User Pool ID
    idToken); // ID Token

var identityId = await client.GetIdAsync(getIdentityIdRequest);

var getCredentialsRequest = new GetCredentialsForIdentityRequest()
{
    IdentityId = identityId.IdentityId
};

getCredentialsRequest.Logins.Add(
    "cognito-idp.us-east-1.amazonaws.com/us-east-1****",
    idToken);

var credentials = await client.GetCredentialsForIdentityAsync(getCredentialsRequest);

// Use credentials.Credentials when calling AWS services

您将需要ID令牌,因此首先进行身份验证并从响应中获取ID令牌。如果持有ID令牌的用户属于Cognito中具有分配的IAM角色的组,则从上述代码返回的凭据将用于该角色。如果未将用户分配给组或该组没有角色,则将获得分配给身份池的已认证用户IAM角色的凭据。

此外,正如@thomasmichaelwallace所建议的那样,可以从Lambda或从外部API Gateway / Lambda进行上述操作,但前提是您使用的是AWS_IAM Authorizer,因为它是唯一接受密钥和访问密钥进行授权的命令。如果您像我以前一样使用Cognito Authorizer,则需要将ID令牌传递给lambda,并让lambda获得凭据。

1 个答案:

答案 0 :(得分:1)

在您的示例中,您为此有效地使用了“内置”方法(Cognito Federated Identities)。可以说,您甚至可以更进一步,使用这些凭据直接从应用程序访问资源(而不是使用API​​-Gateway + Lambda)。

Lambda中的执行角色是调用lambda的角色(凭证)(不需要设置它们,您也不需要调用new CognitoAWSCredentials)。正如您所建议的那样,这是为了限制lambda可以执行的操作(基于每个lambda,而不是调用程序)。

如果Cognito联合身份为您工作,那么使用它们就很有意义,因为它们提供了一种使用IAM实施应用程序授权层的方法;可以说意味着您有责任减少建筑量。并非所有应用程序都适合这种模式,这就是AWS为您提供选项的原因。