2
votes

What I did:

  1. I created a VPC Peering connection between these accounts
  2. Internet Gateways also attached to each VPC
  3. Route Tables also configured (to allow traffic from both sides)

Case 1:

I successfully tested invoking Lambda function (in VPC B) from another Lambda function (in VPC A) when these 2 VPCs are in same account.

However, when I created a similar VPC (as VPC B) in another account (account B) I got the following error:

"errorMessage": "An error occurred (AccessDeniedException) when calling the Invoke operation: User: arn:aws:sts::Account-A:assumed-role/role-for-vpc-peering-test/lambda1_in_vpc is not authorized to perform: lambda:InvokeFunction on resource: arn:aws:lambda:us-east-1:Account-B:function:lambda-vpc

My trails:

I created a cross-account IAM Role for account A in account B with the following permissions:

IAM Role

Then I added an inline policy for the role which is using Lambda in account A:

IAM Permissions

Added policy to above role only:

{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Action": "sts:AssumeRole",
        "Resource": "arn:aws:iam::Account B:role/role-for-Account-A"
    }
}

So my questions is should I do anything else to invoke Lambda in account B from Lambda in account A?

I think I am missing something in the cross-account role only (access denied error).

lambda- A code:

import json import boto3

client = boto3.client('lambda')

def lambda_handler(event, context): inputForInvoker = {'CustomerId': '123', 'Amount': 50 }

response = client.invoke(
    FunctionName='arn:aws:lambda:us-east-1:AccountB-id:function:lambda-vpc-peering',
    InvocationType='RequestResponse', # Event
    Payload=json.dumps(inputForInvoker)
    )

responseJson = json.load(response['Payload'])

print('\n')
print(responseJson)
print('\n')

Any suggestions?

Assume role- in Account b is : have following Policies : 1. AWSLambdaBasicExecutionRole 2.trust-policy:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::Account-id-A:role/role-for-vpc-peering-test"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}. 

execution role - attached this inline policy :

{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Action": "sts:AssumeRole",
        "Resource": "arn:aws:iam::Account-b-id:role/role-for-7691-4701-2358"
    }
}

and updated my lambda function with below mention code also.

but still getting same error

now lambdas are not in vpc.

1
What's your lambda code in A? You have to assume the role in B, using, e.g. sts.assume_role(...) boto3 call.Marcin
yaa i created cross accout role in account b only to use in account AMaldanna Gk
I will and answer, as I don't want to paste code in comment.Marcin

1 Answers

2
votes

General steps required for assuming a role in Account A to do something in Account B (e.g. invoke lambda function in B) are listed in the following AWS blog:

The important thing to note is that the lambda function in Account A has to assume role in Account B. The assumable role must allow execution role of function A to invoke function in B.

I modified your code for lambda in Account A, based on the example from the above link.

The key elements to focus are:

  • sts = boto3.client('sts')
  • account_b = sts.assume_role(...)
  • account_b_client = boto3.client(...)

Assuming that all your roles are correctly set, your code should look something like blow. Obviously you have to adjust it exactly to your needs, but it should give you general idea of what to do in your lambda in Account A.

import json 
import boto3 

client = boto3.client('lambda') 

sts = boto3.client('sts')

def lambda_handler(event, context): 

    inputForInvoker = {'CustomerId': '123', 'Amount': 50 } 

    account_b = sts.assume_role(
        RoleArn="<arn-of-assumbale-role-in-acccount-b>",
        RoleSessionName="cross_acct_lambda"
    )

    ACCESS_KEY = account_b['Credentials']['AccessKeyId']
    SECRET_KEY = account_b['Credentials']['SecretAccessKey']
    SESSION_TOKEN = account_b['Credentials']['SessionToken']

    # create service client using the assumed role credentials
    # from account B
    account_b_client = boto3.client(
        'lambda',
        aws_access_key_id=ACCESS_KEY,
        aws_secret_access_key=SECRET_KEY,
        aws_session_token=SESSION_TOKEN)

    response = account_b_client.invoke(FunctionName='arn:aws:lambda:us-east-1:AccountB-id:function:lambda-vpc-peering', InvocationType='RequestResponse') 

    responseJson = json.load(response['Payload']) 
    print('\n') print(responseJson) print('\n') 

p.s.

  1. I created a VPC Peering connection between these accounts

This is not needed. Invocation of function B from function A will go over internet anyway. So if you don't use the peering connection for anything other, that its not used for the lambdas.