How do I create a cross-account Lambda function to access Amazon Redshift in a different account?

5 minute read
0

I want to create a cross-account AWS Lambda function to access Amazon Redshift that's in a different AWS account.

Resolution

Create a VPC, subnet group, and private Amazon Redshift cluster in your Amazon Redshift account

Complete the following steps from your Amazon Redshift account:

  1. Create a virtual private cloud (VPC) with a private subnet.
  2. Create a cluster subnet group, and then add the VPC and subnet to the cluster subnet group.
  3. Create a private Amazon Redshift cluster, and then add the VPC and cluster subnet group to the cluster.
  4. Use the AWS Secrets Manager console to create a secret for your Amazon Redshift function, and then name your secret.
  5. Create an AWS Identity and Access Management (IAM) role to allow Lambda to access Amazon Redshift. In the following example, the role is named cross-account-child:
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "VisualEditor0",
                "Effect": "Allow",
                "Action": [
                    "secretsmanager:*",
                    "redshift-data:*",
                    "kms:*",
                    "redshift:*",
                    "sts:*"
                ],
                "Resource": "*"
            }
        ]
    }
    Important: When you create IAM policies, it's a best practice to grant only the permissions that are required to perform a specific task. For more information, see Apply least-privilege permissions.
  6. Create a trust relationship to allow the role from your Lambda account to assume the role in your Amazon Redshift account:
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Principal": {
                    "AWS": "arn:aws:iam::Account_B:role/lambdaArticle"
                },
                "Action": "sts:AssumeRole"
            },
            {
                "Effect": "Allow",
                "Principal": {
                    "Service": "redshift.amazonaws.com"
                },
                "Action": "sts:AssumeRole"
            }
        ]
    }
    Note: In the preceding example, replace Account_B with the Lambda account number. The trust relationship also allows Lambda to access Amazon Redshift from the same account.

Create a trust relationship and IAM policy in your Lambda account

Complete the following steps from your Lambda account:

  1. Create a trust relationship to allow the role from the Lambda account to assume the role in the Amazon Redshift account:

    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Principal": {
                    "Service": [
                        "redshift.amazonaws.com",
                        "lambda.amazonaws.com"
                    ]
                },
                "Action": "sts:AssumeRole"
            },
            {
                "Sid": "AssumeRole",
                "Effect": "Allow",
                "Principal": {
                    "AWS": "arn:aws:iam::Account_A:role/cross-account-child"
                },
                "Action": "sts:AssumeRole"
            }
        ]
    }

    Note: Replace Account_A with your Amazon Redshift account number. The trust relationship also allows Lambda to access Amazon Redshift.

  2. Create a IAM policy with the following permissions:

    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "VisualEditor0",
                "Effect": "Allow",
                "Action": [
                    "secretsmanager:*",
                    "redshift-data:*",
                    "kms:*",
                    "redshift:*",
                    "sts:*"
                ],
                "Resource": "*"
            }
        ]
    }
  3. Add the AWSLambdaVPCAccessExecutionRole managed policy to the Lambda role.

Create your Lambda function

To create a Lambda function that queries your Amazon Redshift cluster, complete the following steps:

  1. Open the Lambda console.
  2. Choose Create function.
  3. Choose Author from Scratch.
  4. Add the following information:
    Function name: Enter a custom name.
    Runtime: Enter your code environment. The examples in this resolution are compatible with Python 3.9.
    Architecture: Enter your system architecture. The examples in this resolution are compatible with x86_64.
    Permissions: Choose Create a new role with basic Lambda permissions.
  5. Choose Create function.

Set the permissions for your Lambda function

Complete the following steps:

  1. Open the Lambda console.
  2. Choose Configuration.
  3. Choose Permissions.
  4. Choose the Lambda function role.
    Note: It's a best practice to grant only the permissions that are required to perform a task. For more information, see Apply least-privilege permissions.
  5. Choose Code.
  6. Enter the following Lambda code into the Code box:
    Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
    
    Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so.
    
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR APARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTIONOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    
    import os
    import json
    import boto3
    import botocore 
    import botocore.session as bc
    from botocore.client 
    import Config 
    
    print('Loading function')
    secret_name=os.environ['SecretId']
    
    def lambda_handler(event, context):
        sts_connection = boto3.client('sts')
        acct_b = sts_connection.assume_role(
            RoleArn="arn:aws:iam::Account_A:role/cross-account-child",  
            RoleSessionName="cross_acct_lambda"
        )
    
        ACCESS_KEY = acct_b['Credentials']['AccessKeyId']
        SECRET_KEY = acct_b['Credentials']['SecretAccessKey']
        SESSION_TOKEN = acct_b['Credentials']['SessionToken']
    
        client = boto3.client(
            'secretsmanager',
            aws_access_key_id=ACCESS_KEY,
            aws_secret_access_key=SECRET_KEY,
            aws_session_token=SESSION_TOKEN,
        )
    
        get_secret_value_response = client.get_secret_value(
            SecretId=secret_name
         )
    
        secret_arn=get_secret_value_response['ARN']
        print(secret_arn)
        secret = get_secret_value_response['SecretString']
        print(secret)
        secret_json = json.loads(secret)
        cluster_id=secret_json['dbClusterIdentifier']
        print(cluster_id)
    
        rsd = boto3.client(
            'redshift-data',
            aws_access_key_id=ACCESS_KEY,
            aws_secret_access_key=SECRET_KEY,
            aws_session_token=SESSION_TOKEN,
        )
        resp = rsd.execute_statement(
        SecretArn=secret_arn,
        ClusterIdentifier=cluster_id,
        Database="dev",          
        Sql="create table public.lambda_func (id int);")
        return "Hello from Lambda"
    Note: Replace dev with the name of your database. Add an environment variable that's named SecretId in the Lambda function's configuration section. For RoleArn, add the ARN of the secrete from your Amazon Redshift account. Replace create table public.lambda_func with the query that you want to run to receive a response for.
AWS OFFICIAL
AWS OFFICIALUpdated 5 months ago