AWS Service Account Integrations
Problem
You are building interactive or rendered content in Python or R which needs to access a private AWS resource using an IAM role. The content must authenticate to AWS using a workload identity token that is generated by Connect. This is made possible by adding an AWS service account integration to your content in the content access panel.
Solution
The examples below illustrate how to use the OAuth integrations feature of Posit Connect to delegate authorization for access to an external provider’s resources. In this case, we are focusing on S3 within AWS. These examples use the viewer’s OIDC token to assume an AWS IAM role that provides temporary session credentials to the content. These credentials are used to call the AWS API on behalf of the content viewer.
Ensure the following dependencies are installed:
boto3
posit-sdk>=0.9.0
Make sure to set the following additional environment variables for local development:
AWS_REGION
AWS_BUCKET_NAME
AWS_S3_FILEPATH
import os
import pandas as pd
import boto3
from posit.connect import Client
from posit.connect.external import aws
# Obtain AWS credentials and start a session:
# 1. If running on Posit Connect, perform a credential exchange with the
# content session token that is provided at app startup.
# 2. If running locally, initialize a session using your preferred method.
# This example assumes the use of the aws cli to authenticate.
if os.getenv("POSIT_PRODUCT") == "CONNECT":
= Client()
client # exchange content session token for Service Account AWS credentials
# Connect makes the content session token available in the
# environment variable `CONNECT_CONTENT_SESSION_TOKEN`.
= aws.get_content_credentials(client)
aws_credentials = boto3.Session(
aws_session =aws_credentials["aws_access_key_id"],
aws_access_key_id=aws_credentials["aws_secret_access_key"],
aws_secret_access_key=aws_credentials["aws_session_token"],
aws_session_token
)else:
# Use default credentials from environment/config
= boto3.Session()
aws_session
# Create an S3 client using the AWS session
= aws_session.client("s3")
s3
# Define bucket and key (file path)
= os.getenv("AWS_BUCKET_NAME")
bucket_name = os.getenv("AWS_S3_FILEPATH")
key
# Get the object from S3
= s3.get_object(Bucket=bucket_name, Key=key)
obj
# Read the CSV data into a pandas DataFrame
= pd.read_csv(obj["Body"]) df
Ensure you have the following dependencies installed:
connectapi
arrow
Make sure to set the following additional environment variables for local development:
AWS_REGION
AWS_BUCKET_NAME
AWS_S3_FILEPATH
library(connectapi)
library(arrow)
# Obtain AWS credentials and start a session:
# 1. If running on Posit Connect, perform a credential exchange with the
# content session token that is provided at app startup.
# 2. If running locally, initialize a session using your preferred method.
# This example assumes the use of the aws cli to authenticate.
<- NULL
bucket <- Sys.getenv("AWS_BUCKET_NAME")
bucket_name <- Sys.getenv("AWS_S3_FILEPATH")
filepath
# if running on Connect
if (Sys.getenv("POSIT_PRODUCT") == "CONNECT") {
# init Posit Connect API client
<- connect()
client <- get_aws_content_credentials(client)
credentials <- arrow::s3_bucket(bucket_name,
bucket access_key = credentials$access_key_id,
secret_key = credentials$secret_access_key,
session_token = credentials$session_token
)else {
} # Use default credentials from environment/config
<- arrow::s3_bucket(bucket_name)
bucket
}
# Get the object from S3 and read into dataframe
# Assumes csv file. Use other file reader functions
# for other file types e.g. arrow::read_parquet().
<- arrow::read_csv_arrow(bucket$path(filepath)) df