This page explains the two sides of access control when using Proxylity UDP Gateway with Infrastructure as Code:
For each subscribed AWS account, Proxylity maintains an S3 object in each region containing the specific configuration needed to use Proxylity CloudFormation custom resources. This object contains your account's:
The S3 location follows this pattern:
s3://proxylity-config-${AWS::Region}/${AWS::AccountId}/customer-config.json
This object is automatically created and managed by Proxylity—you don't need to create it manually or modify it. Access to read the object is limited to the associated AWS account only.
The recommended approach is to import this configuration into CloudFormation Mappings at deployment
time using AWS::Include:
"Mappings": {
"ProxylityConfig": {
"Fn::Transform": {
"Name": "AWS::Include",
"Parameters": {
"Location": {
"Fn::Sub": "s3://proxylity-config-${AWS::Region}/${AWS::AccountId}/customer-config.json"
}
}
}
}
}
This makes configuration values available throughout your template via Fn::FindInMap. See the
dns-filter example for a complete working
template.
The S3 configuration object contains sensitive values (your External ID and service credentials). You should use IAM policies to restrict which users and roles in your account can access these resources.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowProxylityConfigAccess",
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": {
"Fn::Sub": "arn:aws:s3:::proxylity-config-${AWS::Region}/${AWS::AccountId}/customer-config.json"
}
}
]
}
Attach this policy (or equivalent) only to the roles and users that deploy Proxylity CloudFormation stacks. Avoid granting broad access to these resources across your organization.
To deliver packets to your AWS resources, Proxylity assumes an IAM role that you define. This gives you full control over what Proxylity can access in your account.
We strongly recommend creating a separate IAM role for each destination with only the permissions needed. This follows the principle of least privilege and makes it easy to audit and revoke access.
Each destination should have its own role with minimal permissions—for example,
lambda:InvokeFunction for Lambda destinations, sns:Publish for SNS, etc.
Here's a CloudFormation snippet that creates a role allowing Proxylity to invoke a specific Lambda function:
{
"ProxylityDestinationRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"AWS": { "Fn::FindInMap": ["ProxylityConfig", "Account", "ServiceTokenArn"] }
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": { "Fn::FindInMap": ["ProxylityConfig", "Account", "ExternalId"] }
}
}
}]
},
"Policies": [{
"PolicyName": "LambdaInvokePolicy",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": "lambda:InvokeFunction",
"Resource": { "Fn::GetAtt": ["YourLambdaFunction", "Arn"] }
}]
}
}]
}
}
}
Key elements of this pattern:
For global deployments, you may need a single role that covers resources in multiple regions. A simple approach is to wildcard the region in resource ARNs and use a hard-coded resource name:
"Statement": [
{
"Sid": "Lambda",
"Effect": "Allow",
"Action": [
"lambda:InvokeFunction"
],
"Resource": [
{
"Fn::Sub": "arn:aws:lambda:*:${AWS::AccountId}:function:dns-filter"
},
{
"Fn::Sub": "arn:aws:lambda:*:${AWS::AccountId}:function:dns-filter:*"
}
]
}
]
See the dns-filter and packet-counter-multi-region examples for complete multi-region templates.