Skip to content

Cross-Account Setup

calculatecost4 runs in the villa-ecommerce AWS account (017176210331) but accesses DynamoDB tables and Lambda functions in the source account (394922924679).


Accounts

Account ID Role
Villa E-commerce 017176210331 Hosts calculatecost4 Lambda + API Gateway
Source (default) 394922924679 Hosts DynamoDB tables + downstream Lambda functions

IAM Role in Source Account

Role name: villaCalculateCost4-CrossAccountAccess

Trust policy (allows villa-ecommerce account to assume this role):

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {"AWS": "arn:aws:iam::017176210331:root"},
    "Action": "sts:AssumeRole"
  }]
}

Permissions policy (DynamoDB read + Lambda invoke):

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["dynamodb:GetItem", "dynamodb:Query", "dynamodb:Scan", "dynamodb:BatchGetItem"],
      "Resource": [
        "arn:aws:dynamodb:ap-southeast-1:394922924679:table/price-database-2-*",
        "arn:aws:dynamodb:ap-southeast-1:394922924679:table/product-table-*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": "lambda:InvokeFunction",
      "Resource": [
        "arn:aws:lambda:ap-southeast-1:394922924679:function:coupon3-checker-dev",
        "arn:aws:lambda:ap-southeast-1:394922924679:function:get-voucher-master",
        "arn:aws:lambda:ap-southeast-1:394922924679:function:get-nationwide-delivery-cost2-master"
      ]
    }
  ]
}

SAM Template Configuration

The calculatecost4 Lambda role is granted sts:AssumeRole permission via the SAM template:

Policies:
  - Version: "2012-10-17"
    Statement:
      - Effect: Allow
        Action: sts:AssumeRole
        Resource:
          - !Sub "arn:aws:iam::${SourceAccountId}:role/villaCalculateCost4-CrossAccountAccess"

Environment variables pass the cross-account configuration:

Environment:
  Variables:
    CROSS_ACCOUNT_ROLE_ARN: !Sub "arn:aws:iam::${SourceAccountId}:role/villaCalculateCost4-CrossAccountAccess"
    COUPON_FUNCTION_ARN: !Sub "arn:aws:lambda:${REGION}:${SourceAccountId}:function:coupon3-checker-dev"
    VOUCHER_FUNCTION_ARN: !Sub "arn:aws:lambda:${REGION}:${SourceAccountId}:function:get-voucher-master"
    NATIONWIDE_FUNCTION_ARN: !Sub "arn:aws:lambda:${REGION}:${SourceAccountId}:function:get-nationwide-delivery-cost2-master"

How cross_account.py Works

# Simplified flow
sts = boto3.client("sts")
creds = sts.assume_role(
    RoleArn=os.environ["CROSS_ACCOUNT_ROLE_ARN"],
    RoleSessionName="calculatecost4",
)["Credentials"]

session = boto3.Session(
    aws_access_key_id=creds["AccessKeyId"],
    aws_secret_access_key=creds["SecretAccessKey"],
    aws_session_token=creds["SessionToken"],
)

# All adapters use this session for DynamoDB and Lambda calls
dynamodb = session.resource("dynamodb")
lambda_client = session.client("lambda")

The session is cached with @lru_cache so AssumeRole is called only once per Lambda cold start.


Lambda Resource-Based Policies

Each Lambda in the source account also has a resource-based policy allowing the villa-ecommerce Lambda role to invoke it:

aws lambda add-permission \
  --function-name coupon3-checker-dev \
  --statement-id villaCalculateCost4CrossAccount \
  --action lambda:InvokeFunction \
  --principal "arn:aws:iam::017176210331:role/villaCalculateCost4-CalculateCost4Role-..." \
  --region ap-southeast-1

Adding New Cross-Account Resources

To add a new DynamoDB table or Lambda function:

  1. Add the resource ARN to the villaCalculateCost4-CrossAccountAccess role policy in account 394922924679
  2. Add the resource ARN to the SAM template policies in template.yaml
  3. Add a resource-based policy on the Lambda (if applicable) allowing the villa-ecommerce role
  4. Add the function ARN as an environment variable in template.yaml
  5. Create a new adapter in calculatecost4/adapters/ that reads the ARN from the environment variable