首页 > 解决方案 > 账户之间的 Lambda 查询问题

问题描述

我正在努力锻炼我做错了什么。我有 2 个帐户:

账户 A - 11111111111

账户 B - 22222222222

账户 A 是我们的登录账户,它包含所有用户详细信息 账户 B 是我们的产品账户。

我想在账户 B 中运行我的 Lambda 并报告账户 A 中的数据。目前,当我运行 lambda 时,我收到以下错误:

An error occurred (AccessDenied) when calling the ListUsers operation: User: arn:aws:sts::2222222222:assumed-role/svc_pct_iam_lambda_role/unusedaccount_lambda_function is not authorized to perform: iam:ListUsers on resource: arn:aws:iam::2222222222:user/: ClientError

我认为的错误是它在 lambda 正在运行的帐户中使用当前的 BotoClient,而不是我允许访问的地方。所以它正在查询帐户 222222222 而不是 1111111

账户 A 具有以下角色和策略

resource "aws_iam_role" "svc_pct_iam_lambda_role" {
  name = "svc_pct_iam_lambda_role"

  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
}

resource "aws_iam_role_policy" "svc_pct_iam_lambda_access_policy" {
  name = "svc_pct_iam_lambda_access_policy"
  role = "${aws_iam_role.svc_pct_iam_lambda_role.id}"

  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "sts:AssumeRole",
      "Resource": "arn:aws:iam::2222222222:role/svc_pct_iam_lambda_role"
    }
  ]
}
EOF
}

resource "aws_iam_policy" "svc_pct_iam_lambda_policy" {
  name = "svc_pct_iam_lambda_policy"

  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "iam:ListUsers",
        "iam:ListMFADevices",
        "iam:ListVirtualMFADevices",
        "SNS:Publish",
        "iam:ListAccessKeys",
        "iam:ListUserPolicies",
        "iam:ListGroupsForUser"
      ],
      "Effect": "Allow",
      "Resource": "*"
    }
  ]
}
EOF
}

resource "aws_iam_role_policy_attachment" "role-attach-svc-pct-iam-lambda-role" {
  role       = "${aws_iam_role.svc_pct_iam_lambda_role.name}"
  policy_arn = "${aws_iam_policy.svc_pct_iam_lambda_policy.arn}"
}

Lambda所在账户B中的策略是:

"resource "aws_iam_role" "svc_pct_iam_lambda_role" {
  name = "svc_pct_iam_lambda_role"

  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
}

resource "aws_iam_role_policy" "svc_pct_iam_lambda_policy" {
  name = "svc_pct_iam_lambda_policy"
  role = "${aws_iam_role.svc_pct_iam_lambda_role.id}"

  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "sts:AssumeRole",
      "Resource": "arn:aws:iam::1111111111:role/svc_pct_iam_lambda_role"
    }
  ]
}
EOF
}

拉姆达是

import boto3
import datetime
from dateutil.tz import tzutc
def lambda_handler(context,event):

    resource = boto3.resource('iam')
    client = boto3.client("iam")

    today = datetime.datetime.now()

    for user in resource.users.all():
        if user.password_last_used is not None:
            delta = (today - user.password_last_used.replace(tzinfo=None)).days
            if delta >= 60:
                print("Username: ",[user.user_name], delta)

标签: pythonaws-lambda

解决方案


为了使 AWS Lambda 函数能够访问 Account-A 中的资源,它需要从 Account-A承担 IAM 角色

因此,它将:

  • 使用账户 B 中的 IAM 角色
  • 打电话AssumeRole()
  • 它返回一组临时凭据
  • 然后可以使用这些临时凭证对 Account-A 进行 API 调用

以下是切换到 IAM 角色 (AWS API) - AWS Identity and Access Management的一些示例代码:

import boto3

# create an STS client object that represents a live connection to the STS service
sts_client = boto3.client('sts')

# Call the assume_role method of the STSConnection object and pass the role ARN and a role session name.
assumed_role_object=sts_client.assume_role(
    RoleArn="arn:aws:iam::account-of-role-to-assume:role/name-of-role",
    RoleSessionName="AssumeRoleSession1"
)

# From the response that contains the assumed role, get the temporary 
# credentials that can be used to make subsequent API calls
credentials=assumed_role_object['Credentials']

# Use the temporary credentials that AssumeRole returns to make a 
# connection to Amazon S3  
s3_resource=boto3.resource(
    's3',
    aws_access_key_id=credentials['AccessKeyId'],
    aws_secret_access_key=credentials['SecretAccessKey'],
    aws_session_token=credentials['SessionToken'],
)

# Use the Amazon S3 resource object that is now configured with the 
# credentials to access your S3 buckets. 
for bucket in s3_resource.buckets.all():
    print(bucket.name)

推荐阅读