AWS IAM reference
This page is the full policy-by-policy reference for the IAM resources LakeSail's CloudFormation template installs in your AWS account when you connect a cloud account. It complements the higher-level Security & IAM page: that page explains the trust model, deployment flow, and what LakeSail can and cannot do; this page is the JSON.
Every JSON block on this page is rendered with placeholders for the values CloudFormation substitutes at deploy time:
<account-id>: your 12-digit AWS account ID (${AWS::AccountId})<region>: the AWS region where you deploy the stack (${AWS::Region})<connection-id>: the 10-character LakeSail connection identifier (${LakeSailConnectionID})<connection-id-lower>: the lowercase form, used by S3 bucket policies (${LakeSailConnectionIDLower})<external-id>: the per-connection UUIDv4 LakeSail shows you once (${LakeSailExternalID})<role-arn>: the ARN of the role you create (you pick the name withIamRoleName)<role-name>: the role's name (${IamRoleName})<stack-name>: the name of the connection's CloudFormation stack (${AWS::StackName})
In addition, several ARNs reference the fixed LakeSail platform AWS account, 921150455437. This is the real, stable production value (LakeSail's own AWS account); it is hard-coded in the template via the LakeSailAccountID and LakeSailPrincipal parameters and is reproduced literally on this page.
The canonical, authoritative form of every policy below is the CloudFormation template LakeSail provides for your connection, which you can download pre-filled from your LakeSail console (Settings → Cloud Accounts → Add AWS Account → Advanced → Download Template). Use this page for review; deploy from the template.
You probably don't need this page
You don't need this reference to evaluate or use LakeSail. The Security & IAM page covers the trust model, what LakeSail provisions, and what it can and cannot do, in plain language. This page exists for one job: letting your security team audit every individual IAM action and condition.
Parameters
The template takes the following parameters. The read-only ones are filled in for you when you launch the stack from the LakeSail UI; if you deploy manually, don't change them, because the trust only works with the values LakeSail recorded for your connection.
| Parameter | Meaning |
|---|---|
IamRoleName | You pick the role name. Useful if you want it to match an internal convention. |
IamPathPrefix | Optional IAM path prefix for organizing the role (e.g., /lakesail/). Defaults to /. |
IamPermissionBoundaryName | Reserved; not currently applied. The boundary policies are named from the connection ID (lakesail-<connection-id>-RoleBoundary and -WorkloadBoundary), not from this value. |
LakeSailAccountID | AWS account of the LakeSail control plane. Read-only. |
LakeSailVPCID | LakeSail's platform VPC, used for peering restrictions. Read-only. |
LakeSailTenantID | Your LakeSail tenant identifier. Read-only. |
LakeSailConnectionID | Internal connection identifier (10 chars). Read-only. |
LakeSailConnectionIDLower | Lowercase form of LakeSailConnectionID, used by S3 bucket policies. Read-only. |
LakeSailExternalID | The STS external ID used in the trust policy. Must not leak. It is the second factor preventing confused-deputy attacks. |
LakeSailPrincipal | The LakeSail IAM principal allowed to assume the role. |
LakeSailCallbackURL | LakeSail webhook URL for stack lifecycle notifications. Read-only. |
Placement in the stack
The CloudFormation stack creates the following IAM resources:
| Resource | Type | Section on this page |
|---|---|---|
LakeSailRole | AWS::IAM::Role | Trust policy |
LakeSailRoleBoundary | AWS::IAM::ManagedPolicy (boundary) | Role boundary |
LakeSailWorkloadBoundary | AWS::IAM::ManagedPolicy (boundary) | Workload boundary |
DenyBoundaryModification | AWS::IAM::ManagedPolicy (attached to LakeSailRole) | Explicit deny on boundary modification |
PolicyEKS | AWS::IAM::ManagedPolicy (attached to LakeSailRole) | PolicyEKS |
PolicyAutoScaling | AWS::IAM::ManagedPolicy (attached to LakeSailRole) | PolicyAutoScaling |
PolicyNetworkReadAndTag | AWS::IAM::ManagedPolicy (attached to LakeSailRole) | PolicyNetworkReadAndTag |
PolicyNetworkCompute | AWS::IAM::ManagedPolicy (attached to LakeSailRole) | PolicyNetworkCompute |
PolicyNetworkManage | AWS::IAM::ManagedPolicy (attached to LakeSailRole) | PolicyNetworkManage |
PolicyIAMAndCloudwatch | AWS::IAM::ManagedPolicy (attached to LakeSailRole) | PolicyIAMAndCloudwatch |
PolicyCloudFormationAndObservabilityAndIdentity | AWS::IAM::ManagedPolicy (attached to LakeSailRole) | PolicyCloudFormationAndObservabilityAndIdentity |
LakeSailCallbackRole | AWS::IAM::Role | Callback role and Lambda |
LakeSailCallbackFunction | AWS::Lambda::Function | Callback role and Lambda |
The two boundaries differ in scope:
LakeSailRoleBoundaryis attached toLakeSailRole. It caps which AWS service namespaces the role can ever touch.LakeSailWorkloadBoundaryis attached to every IAM role LakeSail creates inside your account for cluster, node group, IRSA, and Karpenter use. Its attachment is enforced by a condition oniam:CreateRoleinPolicyIAMAndCloudwatch, so LakeSail cannot create a workload role without one of these boundaries.
Trust policy
Attached to LakeSailRole. Allows only the LakeSail platform principal to assume the role, and requires the connection-specific external ID.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::921150455437:root"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "<external-id>"
}
}
}
]
}The principal is constrained to a 12-digit AWS account root ARN by the CloudFormation parameter LakeSailPrincipal (^arn:aws:iam::\d{12}:root$); the value is fixed to LakeSail's platform AWS account 921150455437. The external ID is constrained to a UUIDv4 (^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$).
Role boundary
Caps LakeSailRole to a fixed allow-list of AWS service namespaces. Anything outside (DynamoDB, RDS, SageMaker, IAM Identity Center, Organizations, etc.) is denied even if a per-action policy is later mis-scoped.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowLakeSailActions",
"Effect": "Allow",
"Action": [
"eks:*",
"eks-auth:*",
"ec2:*",
"elasticloadbalancing:*",
"autoscaling:*",
"iam:*",
"logs:*",
"kms:*",
"cloudwatch:*",
"cloudformation:*",
"sts:*",
"ssm:*",
"glue:*",
"s3:*",
"s3express:*",
"s3tables:*",
"s3vectors:*",
"ssmmessages:*",
"ec2messages:*",
"ecr:*",
"servicequotas:*",
"pricing:*",
"acm:*",
"lambda:*"
],
"Resource": "*"
}
]
}Workload boundary
Attached to every IAM role LakeSail creates for cluster compute, node group, IRSA, and Karpenter. Enforced by a condition on iam:CreateRole in PolicyIAMAndCloudwatch, so LakeSail-created roles cannot escape this cap.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowS3Access",
"Effect": "Allow",
"Action": [
"s3vectors:CreateIndex",
"s3vectors:DeleteIndex",
"s3vectors:DeleteVectors",
"s3vectors:GetIndex",
"s3vectors:GetVectorBucket",
"s3vectors:GetVectorBucketPolicy",
"s3vectors:GetVectors",
"s3vectors:ListIndexes",
"s3vectors:ListTagsForResource",
"s3vectors:ListVectorBuckets",
"s3vectors:ListVectors",
"s3vectors:PutVectors",
"s3vectors:QueryVectors",
"s3vectors:TagResource",
"s3vectors:UntagResource",
"s3express:CreateSession",
"s3express:GetAccessPoint",
"s3express:GetAccessPointPolicy",
"s3express:GetAccessPointScope",
"s3express:GetBucketPolicy",
"s3express:GetEncryptionConfiguration",
"s3express:GetLifecycleConfiguration",
"s3express:ListAccessPointsForDirectoryBuckets",
"s3express:ListAllMyDirectoryBuckets",
"s3express:ListTagsForResource",
"s3express:TagResource",
"s3express:UntagResource",
"s3tables:CreateNamespace",
"s3tables:CreateTable",
"s3tables:DeleteNamespace",
"s3tables:DeleteTable",
"s3tables:DeleteTablePolicy",
"s3tables:DeleteTableReplication",
"s3tables:ListNamespaces",
"s3tables:ListTables",
"s3tables:ListTagsForResource",
"s3tables:PutTableData",
"s3tables:PutTableEncryption",
"s3tables:PutTableMaintenanceConfiguration",
"s3tables:PutTablePolicy",
"s3tables:PutTableRecordExpirationConfiguration",
"s3tables:PutTableReplication",
"s3tables:PutTableStorageClass",
"s3tables:RenameTable",
"s3tables:TagResource",
"s3tables:UntagResource",
"s3tables:UpdateTableMetadataLocation",
"s3:AbortMultipartUpload",
"s3:CreateJob",
"s3:DeleteJobTagging",
"s3:DeleteObject",
"s3:DeleteObjectTagging",
"s3:DeleteObjectVersion",
"s3:DeleteObjectVersionTagging",
"s3:DescribeJob",
"s3:DescribeMultiRegionAccessPointOperation",
"s3:ListAccessGrants",
"s3:ListAccessGrantsInstances",
"s3:ListAccessGrantsLocations",
"s3:ListAccessPoints",
"s3:ListAccessPointsForObjectLambda",
"s3:ListBucket",
"s3:ListBucketMultipartUploads",
"s3:ListBucketVersions",
"s3:ListCallerAccessGrants",
"s3:ListJobs",
"s3:ListMultiRegionAccessPoints",
"s3:ListMultipartUploadParts",
"s3:ListStorageLensConfigurations",
"s3:ListStorageLensGroups",
"s3:ListTagsForResource",
"s3:PutBucketTagging",
"s3:PutJobTagging",
"s3:ReplicateDelete",
"s3:ReplicateObject",
"s3:ReplicateTags",
"s3:RestoreObject",
"s3:TagResource",
"s3:UntagResource",
"s3:UpdateJobPriority",
"s3:UpdateJobStatus",
"s3:UpdateObjectEncryption",
"s3:PutObject",
"s3:PutObjectAcl",
"s3:PutObjectRetention",
"s3:PutObjectTagging",
"s3:PutObjectVersionAcl",
"s3:PutObjectVersionTagging",
"s3:Get*",
"s3tables:Get*"
],
"Resource": "*"
},
{
"Sid": "AllowECRPull",
"Effect": "Allow",
"Action": [
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"ecr:BatchCheckLayerAvailability",
"ecr:BatchImportUpstreamImage",
"ecr:GetAuthorizationToken",
"ecr:GetRepositoryPolicy",
"ecr:DescribeRepositories",
"ecr:ListImages",
"ecr:DescribeImages",
"ecr:GetLifecyclePolicy",
"ecr:GetLifecyclePolicyPreview",
"ecr:ListTagsForResource",
"ecr:DescribeImageScanFindings"
],
"Resource": "*"
},
{
"Sid": "AllowCloudWatchLogs",
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"logs:PutLogEvents",
"logs:DescribeLogStreams"
],
"Resource": "*"
},
{
"Sid": "AllowGlueCatalog",
"Effect": "Allow",
"Action": ["glue:*"],
"Resource": "*"
}
]
}The workload boundary's Resource: "*" looks broad, but in practice every workload role this boundary is attached to operates against a single workspace S3 bucket and a single Glue catalog database scoped by name pattern. The bucket policy on the workspace bucket also constrains which buckets are reachable. s3:Get* and s3tables:Get* are the only wildcards; every other action is explicitly enumerated.
Explicit deny on boundary modification
Attached to LakeSailRole. Prevents the role from modifying either boundary except through CloudFormation. An explicit Deny overrides any Allow elsewhere.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyModifyLakeSailRoleBoundary",
"Effect": "Deny",
"Action": [
"iam:SetDefaultPolicyVersion",
"iam:DeletePolicyVersion",
"iam:DeletePolicy",
"iam:CreatePolicyVersion"
],
"Resource": [
"arn:aws:iam::<account-id>:policy/lakesail-<connection-id>-RoleBoundary",
"arn:aws:iam::<account-id>:policy/lakesail-<connection-id-lower>-RoleBoundary",
"arn:aws:iam::<account-id>:policy/lakesail-<connection-id>-WorkloadBoundary",
"arn:aws:iam::<account-id>:policy/lakesail-<connection-id-lower>-WorkloadBoundary"
],
"Condition": {
"StringEquals": {
"aws:PrincipalArn": "<role-arn>"
},
"ForAllValues:StringNotEquals": {
"aws:CalledVia": ["cloudformation.amazonaws.com"]
}
}
}
]
}The aws:CalledVia condition lets a CloudFormation stack update modify the boundaries (because that is how you upgrade the connection); any direct API call from the role is denied.
PolicyEKS
Create and manage EKS clusters, node groups, addons, access entries, and pod identity associations. Required because LakeSail provisions the Kubernetes cluster that runs your compute.
Scoping pattern: ARN pattern (arn:aws:eks:*:<account-id>:*/lakesail*<connection-id>* and the lowercase variant) or resource tag (LakeSail-Connection or Service: LakeSail). eks:CreateCluster is unconditional because AWS does not support resource-level constraints on cluster creation; clusters are tagged at creation time.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowEKSClusterCreate",
"Effect": "Allow",
"Action": ["eks:CreateCluster"],
"Resource": "*"
},
{
"Sid": "AllowEKSDescribeAndList",
"Effect": "Allow",
"Action": [
"eks:DescribeAddonConfiguration",
"eks:DescribeAddonVersions",
"eks:DescribeClusterVersions",
"eks:ListAccessPolicies",
"eks:ListClusters"
],
"Resource": "*"
},
{
"Sid": "AllowEKSDescribeAndListByServiceTag",
"Effect": "Allow",
"Action": ["eks:Describe*", "eks:List*", "eks:TagResource", "eks:UntagResource"],
"Resource": "*",
"Condition": {
"StringEquals": { "aws:ResourceTag/Service": "LakeSail" }
}
},
{
"Sid": "AllowEKSDescribeAndListByConnectionTag",
"Effect": "Allow",
"Action": ["eks:Describe*", "eks:List*", "eks:TagResource", "eks:UntagResource"],
"Resource": "*",
"Condition": {
"StringEquals": { "aws:ResourceTag/LakeSail-Connection": "<connection-id>" }
}
},
{
"Sid": "AllowEKSDescribeAndListByConnectionArn",
"Effect": "Allow",
"Action": ["eks:Describe*", "eks:List*", "eks:TagResource", "eks:UntagResource"],
"Resource": [
"arn:aws:eks:*:<account-id>:*/lakesail*<connection-id>*",
"arn:aws:eks:*:<account-id>:*/lakesail*<connection-id-lower>*"
]
},
{
"Sid": "AllowEKSClusterManagement",
"Effect": "Allow",
"Action": [
"eks:DeleteCluster",
"eks:UpdateClusterConfig",
"eks:UpdateClusterVersion",
"eks:ListNodegroups",
"eks:CreateNodegroup"
],
"Resource": [
"arn:aws:eks:*:<account-id>:cluster/lakesail*<connection-id>*",
"arn:aws:eks:*:<account-id>:cluster/lakesail*<connection-id-lower>*"
]
},
{
"Sid": "AllowEKSTaggingByConnectionTag",
"Effect": "Allow",
"Action": ["eks:TagResource", "eks:UntagResource"],
"Resource": "*",
"Condition": {
"StringEquals": { "aws:ResourceTag/LakeSail-Connection": "<connection-id>" }
}
},
{
"Sid": "AllowEKSTaggingByConnectionArn",
"Effect": "Allow",
"Action": ["eks:TagResource", "eks:UntagResource"],
"Resource": [
"arn:aws:eks:*:<account-id>:*/lakesail*<connection-id>*",
"arn:aws:eks:*:<account-id>:*/lakesail*<connection-id-lower>*"
]
},
{
"Sid": "AllowEKSNodeGroupManagement",
"Effect": "Allow",
"Action": [
"eks:DescribeNodegroup",
"eks:CreateNodegroup",
"eks:DeleteNodegroup",
"eks:UpdateNodegroupConfig",
"eks:UpdateNodegroupVersion"
],
"Resource": [
"arn:aws:eks:*:<account-id>:nodegroup/lakesail*<connection-id>*",
"arn:aws:eks:*:<account-id>:nodegroup/lakesail*<connection-id-lower>*"
]
},
{
"Sid": "AllowEKSAccessManagement",
"Effect": "Allow",
"Action": [
"eks:CreateAccessEntry",
"eks:DeleteAccessEntry",
"eks:DescribeAccessEntry",
"eks:ListAccessEntries",
"eks:UpdateAccessEntry",
"eks:AssociateAccessPolicy",
"eks:DisassociateAccessPolicy",
"eks:ListAccessPolicies",
"eks:ListAssociatedAccessPolicies"
],
"Resource": [
"arn:aws:eks:*:<account-id>:cluster/lakesail*<connection-id>*",
"arn:aws:eks:*:<account-id>:access-entry/lakesail*<connection-id>*",
"arn:aws:eks:*:<account-id>:cluster/lakesail*<connection-id-lower>*",
"arn:aws:eks:*:<account-id>:access-entry/lakesail*<connection-id-lower>*"
]
},
{
"Sid": "AllowEKSAddons",
"Effect": "Allow",
"Action": [
"eks:CreateAddon",
"eks:DeleteAddon",
"eks:DescribeAddon",
"eks:DescribeAddonConfiguration",
"eks:DescribeAddonVersions",
"eks:ListAddons",
"eks:UpdateAddon",
"eks:ListTagsForResource"
],
"Resource": [
"arn:aws:eks:*:<account-id>:cluster/lakesail*<connection-id>*",
"arn:aws:eks:*:<account-id>:addon/lakesail*<connection-id>*",
"arn:aws:eks:*:<account-id>:cluster/lakesail*<connection-id-lower>*",
"arn:aws:eks:*:<account-id>:addon/lakesail*<connection-id-lower>*"
]
},
{
"Sid": "AllowEKSPodIdentity",
"Effect": "Allow",
"Action": [
"eks:CreatePodIdentityAssociation",
"eks:DeletePodIdentityAssociation",
"eks:DescribePodIdentityAssociation",
"eks:ListPodIdentityAssociations",
"eks:UpdatePodIdentityAssociation"
],
"Resource": [
"arn:aws:eks:*:<account-id>:cluster/lakesail*<connection-id>*",
"arn:aws:eks:*:<account-id>:podidentityassociation/lakesail*<connection-id>*",
"arn:aws:eks:*:<account-id>:cluster/lakesail*<connection-id-lower>*",
"arn:aws:eks:*:<account-id>:podidentityassociation/lakesail*<connection-id-lower>*"
]
},
{
"Sid": "AllowIAMReadServiceLinkedRoles",
"Effect": "Allow",
"Action": ["iam:GetRole", "iam:GetRolePolicy"],
"Resource": "*"
}
]
}PolicyAutoScaling
Manage Auto Scaling Groups behind EKS managed node groups and Karpenter NodePools. Every action is gated by the LakeSail-Connection resource tag or by an ARN pattern matching the connection-scoped ASG. Both statements grant the same 44-action list; the second statement applies to ARN-scoped resources, the first applies tag-conditioned to any resource.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowAutoScalingManagementByConnectionTag",
"Effect": "Allow",
"Action": [
"autoscaling:AttachInstances",
"autoscaling:AttachLoadBalancerTargetGroups",
"autoscaling:AttachLoadBalancers",
"autoscaling:AttachTrafficSources",
"autoscaling:BatchDeleteScheduledAction",
"autoscaling:BatchPutScheduledUpdateGroupAction",
"autoscaling:CancelInstanceRefresh",
"autoscaling:CompleteLifecycleAction",
"autoscaling:CreateAutoScalingGroup",
"autoscaling:CreateLaunchConfiguration",
"autoscaling:CreateOrUpdateTags",
"autoscaling:DeleteAutoScalingGroup",
"autoscaling:DeleteLaunchConfiguration",
"autoscaling:DeleteLifecycleHook",
"autoscaling:DeleteNotificationConfiguration",
"autoscaling:DeletePolicy",
"autoscaling:DeleteScheduledAction",
"autoscaling:DeleteTags",
"autoscaling:DeleteWarmPool",
"autoscaling:DetachInstances",
"autoscaling:DetachLoadBalancerTargetGroups",
"autoscaling:DetachLoadBalancers",
"autoscaling:DetachTrafficSources",
"autoscaling:DisableMetricsCollection",
"autoscaling:EnableMetricsCollection",
"autoscaling:EnterStandby",
"autoscaling:ExecutePolicy",
"autoscaling:ExitStandby",
"autoscaling:LaunchInstances",
"autoscaling:PutLifecycleHook",
"autoscaling:PutNotificationConfiguration",
"autoscaling:PutScalingPolicy",
"autoscaling:PutScheduledUpdateGroupAction",
"autoscaling:PutWarmPool",
"autoscaling:RecordLifecycleActionHeartbeat",
"autoscaling:ResumeProcesses",
"autoscaling:RollbackInstanceRefresh",
"autoscaling:SetDesiredCapacity",
"autoscaling:SetInstanceHealth",
"autoscaling:SetInstanceProtection",
"autoscaling:StartInstanceRefresh",
"autoscaling:SuspendProcesses",
"autoscaling:TerminateInstanceInAutoScalingGroup",
"autoscaling:UpdateAutoScalingGroup"
],
"Resource": "*",
"Condition": {
"StringEquals": { "aws:ResourceTag/LakeSail-Connection": "<connection-id>" }
}
},
{
"Sid": "AllowAutoScalingManagementByConnectionArn",
"Effect": "Allow",
"Action": [
"autoscaling:AttachInstances",
"autoscaling:AttachLoadBalancerTargetGroups",
"autoscaling:AttachLoadBalancers",
"autoscaling:AttachTrafficSources",
"autoscaling:BatchDeleteScheduledAction",
"autoscaling:BatchPutScheduledUpdateGroupAction",
"autoscaling:CancelInstanceRefresh",
"autoscaling:CompleteLifecycleAction",
"autoscaling:CreateAutoScalingGroup",
"autoscaling:CreateLaunchConfiguration",
"autoscaling:CreateOrUpdateTags",
"autoscaling:DeleteAutoScalingGroup",
"autoscaling:DeleteLaunchConfiguration",
"autoscaling:DeleteLifecycleHook",
"autoscaling:DeleteNotificationConfiguration",
"autoscaling:DeletePolicy",
"autoscaling:DeleteScheduledAction",
"autoscaling:DeleteTags",
"autoscaling:DeleteWarmPool",
"autoscaling:DetachInstances",
"autoscaling:DetachLoadBalancerTargetGroups",
"autoscaling:DetachLoadBalancers",
"autoscaling:DetachTrafficSources",
"autoscaling:DisableMetricsCollection",
"autoscaling:EnableMetricsCollection",
"autoscaling:EnterStandby",
"autoscaling:ExecutePolicy",
"autoscaling:ExitStandby",
"autoscaling:LaunchInstances",
"autoscaling:PutLifecycleHook",
"autoscaling:PutNotificationConfiguration",
"autoscaling:PutScalingPolicy",
"autoscaling:PutScheduledUpdateGroupAction",
"autoscaling:PutWarmPool",
"autoscaling:RecordLifecycleActionHeartbeat",
"autoscaling:ResumeProcesses",
"autoscaling:RollbackInstanceRefresh",
"autoscaling:SetDesiredCapacity",
"autoscaling:SetInstanceHealth",
"autoscaling:SetInstanceProtection",
"autoscaling:StartInstanceRefresh",
"autoscaling:SuspendProcesses",
"autoscaling:TerminateInstanceInAutoScalingGroup",
"autoscaling:UpdateAutoScalingGroup"
],
"Resource": [
"arn:aws:autoscaling:*:<account-id>:*/lakesail*<connection-id>*",
"arn:aws:autoscaling:*:<account-id>:*/lakesail*<connection-id-lower>*"
]
}
]
}PolicyNetworkReadAndTag
Read-only access to EC2 and ELB, plus the ability to tag resources at creation and later by tag. Used to discover existing VPC state and stamp newly-created resources with the LakeSail tags so other policies can target them.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowEC2DescribeAll",
"Effect": "Allow",
"Action": ["ec2:Describe*", "ec2:GetSpotPlacementScores"],
"Resource": "*"
},
{
"Sid": "AllowVPCTagging",
"Effect": "Allow",
"Action": ["ec2:CreateTags", "ec2:TagResource"],
"Resource": "*",
"Condition": {
"StringLike": {
"ec2:CreateAction": [
"AllocateAddress",
"CreateFleet",
"CreateInternetGateway",
"CreateLaunchTemplate",
"CreateKeyPair",
"CreateNatGateway",
"CreateNetworkAcl",
"CreateNetworkInterface",
"CreateRouteTable",
"CreateSecurityGroup",
"CreateSubnet",
"CreateVolume",
"CreateVpc",
"CreateVpcEndpoint",
"CreateVpcPeeringConnection",
"ImportKeyPair",
"RunInstances"
]
}
}
},
{
"Sid": "AllowEC2ComputeTaggingUpdatesByServiceTag",
"Effect": "Allow",
"Action": ["ec2:CreateTags", "ec2:DeleteTags", "ec2:TagResource", "ec2:UntagResource"],
"Resource": "*",
"Condition": {
"StringEquals": { "aws:ResourceTag/Service": "LakeSail" }
}
},
{
"Sid": "AllowEC2ComputeTaggingUpdatesByConnectionTag",
"Effect": "Allow",
"Action": ["ec2:CreateTags", "ec2:DeleteTags", "ec2:TagResource", "ec2:UntagResource"],
"Resource": "*",
"Condition": {
"StringEquals": { "aws:ResourceTag/LakeSail-Connection": "<connection-id>" }
}
},
{
"Sid": "AllowEC2ComputeTaggingUpdatesByResourceArn",
"Effect": "Allow",
"Action": ["ec2:CreateTags", "ec2:DeleteTags", "ec2:TagResource", "ec2:UntagResource"],
"Resource": [
"arn:aws:ec2:*:<account-id>:*/lakesail*<connection-id>*",
"arn:aws:ec2:*:<account-id>:*/lakesail*<connection-id-lower>*"
]
},
{
"Sid": "AllowSecurityGroupTagging",
"Effect": "Allow",
"Action": ["ec2:CreateTags", "ec2:TagResource"],
"Resource": "arn:aws:ec2:*:<account-id>:security-group/*",
"Condition": {
"StringLike": { "ec2:CreateAction": "CreateSecurityGroup" }
}
},
{
"Sid": "AllowVPCResourceTaggingByServiceTag",
"Effect": "Allow",
"Action": ["ec2:CreateTags", "ec2:TagResource"],
"Resource": [
"arn:aws:ec2:*:<account-id>:elastic-ip/*",
"arn:aws:ec2:*:<account-id>:image/*",
"arn:aws:ec2:*:<account-id>:instance/*",
"arn:aws:ec2:*:<account-id>:internet-gateway/*",
"arn:aws:ec2:*:<account-id>:key-pair/*",
"arn:aws:ec2:*:<account-id>:network-acl/*",
"arn:aws:ec2:*:<account-id>:network-interface/*",
"arn:aws:ec2:*:<account-id>:route-table/*",
"arn:aws:ec2:*:<account-id>:subnet/*",
"arn:aws:ec2:*:<account-id>:security-group/*",
"arn:aws:ec2:*:<account-id>:security-group-rule/*",
"arn:aws:ec2:*:<account-id>:volume/*",
"arn:aws:ec2:*:<account-id>:vpc/*",
"arn:aws:ec2:*:<account-id>:vpc-endpoint/*",
"arn:aws:ec2:*:<account-id>:vpc-peering-connection/*"
],
"Condition": {
"StringEquals": { "aws:RequestTag/Service": "LakeSail" }
}
},
{
"Sid": "AllowVPCResourceTaggingByConnectionTag",
"Effect": "Allow",
"Action": ["ec2:CreateTags", "ec2:TagResource"],
"Resource": [
"arn:aws:ec2:*:<account-id>:elastic-ip/*",
"arn:aws:ec2:*:<account-id>:image/*",
"arn:aws:ec2:*:<account-id>:instance/*",
"arn:aws:ec2:*:<account-id>:internet-gateway/*",
"arn:aws:ec2:*:<account-id>:key-pair/*",
"arn:aws:ec2:*:<account-id>:network-acl/*",
"arn:aws:ec2:*:<account-id>:network-interface/*",
"arn:aws:ec2:*:<account-id>:route-table/*",
"arn:aws:ec2:*:<account-id>:subnet/*",
"arn:aws:ec2:*:<account-id>:security-group/*",
"arn:aws:ec2:*:<account-id>:security-group-rule/*",
"arn:aws:ec2:*:<account-id>:volume/*",
"arn:aws:ec2:*:<account-id>:vpc/*",
"arn:aws:ec2:*:<account-id>:vpc-endpoint/*",
"arn:aws:ec2:*:<account-id>:vpc-peering-connection/*"
],
"Condition": {
"StringEquals": { "aws:RequestTag/LakeSail-Connection": "<connection-id>" }
}
},
{
"Sid": "AllowELBAndAutoScalingDescribe",
"Effect": "Allow",
"Action": ["elasticloadbalancing:Describe*", "autoscaling:Describe*"],
"Resource": "*"
}
]
}PolicyNetworkCompute
Create and modify the EC2 launch templates that back EKS node groups and Karpenter, and the load balancers + target groups that front cluster endpoints.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowEC2Create",
"Effect": "Allow",
"Action": [
"ec2:CreateLaunchTemplate",
"ec2:CreateLaunchTemplateVersion",
"ec2:RunInstances",
"ec2:CreateFleet"
],
"Resource": "*"
},
{
"Sid": "AllowEC2LaunchTemplatesModifyByConnectionTag",
"Effect": "Allow",
"Action": [
"ec2:DeleteLaunchTemplate",
"ec2:DeleteLaunchTemplateVersions",
"ec2:GetLaunchTemplateData",
"ec2:ModifyLaunchTemplate",
"ec2:TerminateInstances"
],
"Resource": "*",
"Condition": {
"StringEquals": { "aws:ResourceTag/LakeSail-Connection": "<connection-id>" }
}
},
{
"Sid": "AllowEC2LaunchTemplatesModifyByConnectionArn",
"Effect": "Allow",
"Action": [
"ec2:DeleteLaunchTemplate",
"ec2:DeleteLaunchTemplateVersions",
"ec2:GetLaunchTemplateData",
"ec2:ModifyLaunchTemplate",
"ec2:TerminateInstances"
],
"Resource": [
"arn:aws:ec2:*:<account-id>:*/lakesail*<connection-id>*",
"arn:aws:ec2:*:<account-id>:*/lakesail*<connection-id-lower>*"
]
},
{
"Sid": "AllowELBCreateByServiceTag",
"Effect": "Allow",
"Action": ["elasticloadbalancing:CreateLoadBalancer", "elasticloadbalancing:CreateTargetGroup"],
"Resource": "*",
"Condition": {
"StringEquals": { "aws:RequestTag/Service": "LakeSail" }
}
},
{
"Sid": "AllowELBCreateByConnectionTag",
"Effect": "Allow",
"Action": ["elasticloadbalancing:CreateLoadBalancer", "elasticloadbalancing:CreateTargetGroup"],
"Resource": "*",
"Condition": {
"StringEquals": { "aws:RequestTag/LakeSail-Connection": "<connection-id>" }
}
},
{
"Sid": "AllowELBListenerTagForCleanup",
"Effect": "Allow",
"Action": ["elasticloadbalancing:AddTags"],
"Resource": "*",
"Condition": {
"StringEquals": { "aws:RequestTag/LakeSail-Connection": "<connection-id>" }
}
},
{
"Sid": "AllowELBManagement",
"Effect": "Allow",
"Action": [
"elasticloadbalancing:CreateLoadBalancer",
"elasticloadbalancing:CreateTargetGroup",
"elasticloadbalancing:DeleteLoadBalancer",
"elasticloadbalancing:ModifyLoadBalancerAttributes",
"elasticloadbalancing:CreateListener",
"elasticloadbalancing:DeleteListener",
"elasticloadbalancing:ModifyListener",
"elasticloadbalancing:CreateRule",
"elasticloadbalancing:DeleteRule",
"elasticloadbalancing:ModifyRule",
"elasticloadbalancing:DeleteTargetGroup",
"elasticloadbalancing:ModifyTargetGroup",
"elasticloadbalancing:ModifyTargetGroupAttributes",
"elasticloadbalancing:RegisterTargets",
"elasticloadbalancing:DeregisterTargets",
"elasticloadbalancing:AddTags",
"elasticloadbalancing:RemoveTags",
"elasticloadbalancing:SetSecurityGroups",
"elasticloadbalancing:SetSubnets",
"elasticloadbalancing:SetIpAddressType"
],
"Resource": "*",
"Condition": {
"StringEquals": { "aws:ResourceTag/LakeSail-Connection": "<connection-id>" }
}
}
]
}PolicyNetworkManage
Create and manage VPC, S3, Glue catalog, SSM parameters, KMS keys, and ACM certificates. The broadest of the seven policies. Every modify/delete action is gated by the LakeSail-Connection tag or by an ARN pattern matching lakesail*<connection-id>*.
Note: ssm:DescribeParameters is granted on Resource: "*" (account-wide) as a separate statement from the connection-scoped SSM parameter management. AWS does not support resource-level scoping on DescribeParameters.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowVPCCreate",
"Effect": "Allow",
"Action": [
"ec2:CreateVpc",
"ec2:CreateSubnet",
"ec2:CreateInternetGateway",
"ec2:CreateNatGateway",
"ec2:CreateRouteTable",
"ec2:CreateSecurityGroup",
"ec2:CreateNetworkAcl",
"ec2:CreateRoute",
"ec2:AllocateAddress",
"ec2:CreateVpcEndpoint"
],
"Resource": "*"
},
{
"Sid": "AllowVPCManageByConnectionArn1",
"Effect": "Allow",
"Action": ["ec2:*"],
"Resource": [
"arn:aws:ec2:*:<account-id>:*/lakesail*<connection-id>*",
"arn:aws:ec2:*:<account-id>:*/lakesail*<connection-id-lower>*"
]
},
{
"Sid": "AllowVPCModifyByConnectionTag",
"Effect": "Allow",
"Action": [
"ec2:DeleteVpc",
"ec2:DeleteSubnet",
"ec2:DeleteInternetGateway",
"ec2:DeleteNatGateway",
"ec2:DeleteRouteTable",
"ec2:DeleteSecurityGroup",
"ec2:DeleteNetworkAcl",
"ec2:CreateRoute",
"ec2:DeleteRoute",
"ec2:ReleaseAddress",
"ec2:AttachInternetGateway",
"ec2:DetachInternetGateway",
"ec2:AssociateRouteTable",
"ec2:DisassociateRouteTable",
"ec2:AssociateSubnetCidrBlock",
"ec2:ModifyVpcAttribute",
"ec2:ModifySubnetAttribute",
"ec2:AuthorizeSecurityGroupIngress",
"ec2:AuthorizeSecurityGroupEgress",
"ec2:RevokeSecurityGroupIngress",
"ec2:RevokeSecurityGroupEgress",
"ec2:CreateNetworkAclEntry",
"ec2:DeleteNetworkAclEntry",
"ec2:ReplaceNetworkAclEntry",
"ec2:DeleteVpcEndpoints",
"ec2:ModifyVpcEndpoint"
],
"Resource": "*",
"Condition": {
"StringEquals": { "aws:ResourceTag/LakeSail-Connection": "<connection-id>" }
}
},
{
"Sid": "AllowS3BucketManagement",
"Effect": "Allow",
"Action": ["s3:*", "s3express:*", "s3tables:*", "s3vectors:*"],
"Resource": [
"arn:aws:s3:::lakesail*<connection-id>*",
"arn:aws:s3:::lakesail*<connection-id>*/*",
"arn:aws:s3:::lakesail*<connection-id-lower>*",
"arn:aws:s3:::lakesail*<connection-id-lower>*/*"
]
},
{
"Sid": "AllowS3ListBuckets",
"Effect": "Allow",
"Action": ["s3:ListAllMyBuckets"],
"Resource": "*"
},
{
"Sid": "AllowGlueCatalogAccess",
"Effect": "Allow",
"Action": [
"glue:GetCatalog",
"glue:GetCatalogs",
"glue:GetCatalogImportStatus",
"glue:GetConnection",
"glue:GetConnections",
"glue:GetDataCatalogEncryptionSettings",
"glue:GetResourcePolicies",
"glue:GetResourcePolicy",
"glue:ImportCatalogToGlue",
"glue:CreateCatalog",
"glue:GetTags",
"glue:CreateDatabase",
"glue:DeleteDatabase",
"glue:UpdateDatabase",
"glue:GetDatabase",
"glue:GetDatabases",
"glue:TagResource",
"glue:UntagResource"
],
"Resource": ["arn:aws:glue:*:<account-id>:catalog"]
},
{
"Sid": "AllowGlueCatalogManagement",
"Effect": "Allow",
"Action": ["glue:*"],
"Resource": [
"arn:aws:glue:*:<account-id>:*/lakesail*<connection-id>*",
"arn:aws:glue:*:<account-id>:*/lakesail*<connection-id>*/*",
"arn:aws:glue:*:<account-id>:*/lakesail*<connection-id-lower>*",
"arn:aws:glue:*:<account-id>:*/lakesail*<connection-id-lower>*/*"
]
},
{
"Sid": "AllowSSMDescribeParameters",
"Effect": "Allow",
"Action": ["ssm:DescribeParameters"],
"Resource": "*"
},
{
"Sid": "AllowSSMParameters",
"Effect": "Allow",
"Action": [
"ssm:DeleteParameter",
"ssm:DeleteParameters",
"ssm:GetParameter",
"ssm:GetParameters",
"ssm:GetParameterHistory",
"ssm:GetParametersByPath",
"ssm:LabelParameterVersion",
"ssm:UnlabelParameterVersion",
"ssm:PutParameter",
"ssm:AddTagsToResource",
"ssm:ListTagsForResource",
"ssm:RemoveTagsFromResource"
],
"Resource": [
"arn:aws:ssm:*:<account-id>:parameter/lakesail*<connection-id>*",
"arn:aws:ssm:*:<account-id>:parameter/lakesail*<connection-id-lower>*"
]
},
{
"Sid": "AllowKMSKeyCreation",
"Effect": "Allow",
"Action": ["kms:CreateKey", "kms:CreateAlias", "kms:DeleteAlias", "kms:TagResource"],
"Resource": "*"
},
{
"Sid": "AllowKMSKeyManagement",
"Effect": "Allow",
"Action": [
"kms:DescribeKey",
"kms:EnableKey",
"kms:DisableKey",
"kms:GetKeyPolicy",
"kms:ListAliases"
],
"Resource": "arn:aws:kms:*:<account-id>:key/*",
"Condition": {
"StringEquals": { "aws:ResourceTag/LakeSail-Connection": "<connection-id>" }
}
},
{
"Sid": "AllowACMCertificateCreate",
"Effect": "Allow",
"Action": ["acm:RequestCertificate", "acm:ListCertificates"],
"Resource": "*"
},
{
"Sid": "AllowACMCertificateManage",
"Effect": "Allow",
"Action": [
"acm:DescribeCertificate",
"acm:DeleteCertificate",
"acm:GetCertificate",
"acm:AddTagsToCertificate",
"acm:RemoveTagsFromCertificate",
"acm:ListTagsForCertificate"
],
"Resource": "arn:aws:acm:*:<account-id>:certificate/*"
}
]
}PolicyIAMAndCloudwatch
Create and manage the IAM roles, policies, and OIDC providers that LakeSail provisions inside the cluster (cluster role, node group role, IRSA roles, Karpenter controller role). Every iam:CreateRole is conditioned on attaching one of the LakeSail boundaries, so LakeSail-created child roles cannot escape the boundary cap. iam:PassRole is scoped to LakeSail-prefixed role ARNs and to specific service principals.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "IAMRoleBoundary",
"Effect": "Allow",
"Action": ["iam:PutRolePermissionsBoundary", "iam:CreateRole"],
"Resource": ["arn:aws:iam::<account-id>:role/lakesail*"],
"Condition": {
"StringEquals": {
"iam:PermissionsBoundary": [
"arn:aws:iam::<account-id>:policy/lakesail-<connection-id>-RoleBoundary",
"arn:aws:iam::<account-id>:policy/lakesail-<connection-id-lower>-RoleBoundary",
"arn:aws:iam::<account-id>:policy/lakesail-<connection-id>-WorkloadBoundary",
"arn:aws:iam::<account-id>:policy/lakesail-<connection-id-lower>-WorkloadBoundary"
]
}
}
},
{
"Sid": "AllowIAMRoleManagement",
"Effect": "Allow",
"Action": [
"iam:DeleteRole",
"iam:GetRole",
"iam:TagRole",
"iam:UntagRole",
"iam:UpdateRole",
"iam:UpdateRoleDescription",
"iam:UpdateAssumeRolePolicy",
"iam:AttachRolePolicy",
"iam:DetachRolePolicy",
"iam:PutRolePolicy",
"iam:DeleteRolePolicy",
"iam:GetRolePolicy",
"iam:ListAttachedRolePolicies",
"iam:ListRolePolicies",
"iam:ListInstanceProfilesForRole"
],
"Resource": [
"arn:aws:iam::<account-id>:role/lakesail*",
"arn:aws:iam::<account-id>:role/aws-service-role/*"
]
},
{
"Sid": "AllowIAMPolicyCreation",
"Effect": "Allow",
"Action": [
"iam:CreatePolicy",
"iam:DeletePolicy",
"iam:GetPolicy",
"iam:GetPolicyVersion",
"iam:ListPolicyVersions",
"iam:TagPolicy",
"iam:UntagPolicy",
"iam:CreatePolicyVersion",
"iam:DeletePolicyVersion"
],
"Resource": ["arn:aws:iam::<account-id>:policy/lakesail*"]
},
{
"Sid": "AllowIAMReadAWSManagedPolicies",
"Effect": "Allow",
"Action": ["iam:GetPolicy", "iam:GetPolicyVersion", "iam:ListPolicyVersions"],
"Resource": "arn:aws:iam::aws:policy/*"
},
{
"Sid": "AllowIAMPassRole",
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": ["arn:aws:iam::<account-id>:role/lakesail*"],
"Condition": {
"StringLike": {
"iam:PassedToService": [
"eks.amazonaws.com",
"ec2.amazonaws.com",
"pods.eks.amazonaws.com"
]
}
}
},
{
"Sid": "AllowIAMServiceLinkedRole",
"Effect": "Allow",
"Action": "iam:CreateServiceLinkedRole",
"Resource": "*",
"Condition": {
"StringEquals": {
"iam:AWSServiceName": [
"eks.amazonaws.com",
"eks-nodegroup.amazonaws.com",
"elasticloadbalancing.amazonaws.com",
"ec2-nat-gateway.amazonaws.com"
]
}
}
},
{
"Sid": "AllowIAMOIDCProvider",
"Effect": "Allow",
"Action": [
"iam:CreateOpenIDConnectProvider",
"iam:DeleteOpenIDConnectProvider",
"iam:GetOpenIDConnectProvider",
"iam:TagOpenIDConnectProvider",
"iam:UpdateOpenIDConnectProviderThumbprint",
"iam:AddClientIDToOpenIDConnectProvider",
"iam:RemoveClientIDFromOpenIDConnectProvider",
"iam:ListOpenIDConnectProviderTags",
"iam:UntagOpenIDConnectProvider",
"iam:ListOpenIDConnectProviders"
],
"Resource": "*"
},
{
"Sid": "AllowIAMDescribe",
"Effect": "Allow",
"Action": ["iam:GetPolicy", "iam:GetPolicyVersion", "iam:ListPolicyVersions"],
"Resource": [
"arn:aws:iam::<account-id>:policy/*<role-name>*",
"arn:aws:iam::<account-id>:policy/lakesail-<connection-id>-RoleBoundary",
"arn:aws:iam::<account-id>:policy/lakesail-<connection-id-lower>-RoleBoundary",
"arn:aws:iam::<account-id>:policy/lakesail-<connection-id>-WorkloadBoundary",
"arn:aws:iam::<account-id>:policy/lakesail-<connection-id-lower>-WorkloadBoundary"
]
},
{
"Sid": "AllowCloudWatchLogsManagement",
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:DeleteLogGroup",
"logs:DescribeLogGroups",
"logs:PutRetentionPolicy",
"logs:TagLogGroup",
"logs:UntagLogGroup"
],
"Resource": [
"arn:aws:logs:*:<account-id>:log-group:/aws/eks/lakesail*<connection-id>*",
"arn:aws:logs:*:<account-id>:log-group:/aws/eks/lakesail*<connection-id-lower>*"
]
}
]
}PolicyCloudFormationAndObservabilityAndIdentity
Read CloudFormation stacks, manage the connection's own stack and the callback Lambda, read CloudWatch metrics, call the Pricing and Service Quotas APIs, assume the LakeSail-side session-proxy DNS role, and manage the connection role itself and the callback role.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowReadMetrics",
"Effect": "Allow",
"Action": [
"cloudwatch:GetMetricData",
"cloudwatch:GetMetricStatistics",
"cloudwatch:ListMetrics"
],
"Resource": "*"
},
{
"Sid": "AllowSTSOperations",
"Effect": "Allow",
"Action": ["sts:DecodeAuthorizationMessage", "sts:GetCallerIdentity"],
"Resource": "*"
},
{
"Sid": "AllowSessionProxyDNSRoleAssume",
"Effect": "Allow",
"Action": ["sts:AssumeRole"],
"Resource": "arn:aws:iam::921150455437:role/lakesail-*-sp-dns"
},
{
"Sid": "AllowServiceQuotasRead",
"Effect": "Allow",
"Action": [
"servicequotas:ListServiceQuotas",
"servicequotas:GetServiceQuota",
"servicequotas:GetAWSDefaultServiceQuota",
"servicequotas:ListAWSDefaultServiceQuotas"
],
"Resource": "*"
},
{
"Sid": "AllowPricingDataAccess",
"Effect": "Allow",
"Action": ["pricing:GetProducts"],
"Resource": "*"
},
{
"Sid": "AllowListLakeSailStacks",
"Effect": "Allow",
"Action": ["cloudformation:ListStacks"],
"Resource": "*"
},
{
"Sid": "AllowDescribeLakeSailStacks",
"Effect": "Allow",
"Action": [
"cloudformation:DescribeStacks",
"cloudformation:DescribeStackResource",
"cloudformation:DescribeStackResources"
],
"Resource": "*"
},
{
"Sid": "AllowUpdateLakeSailStacks",
"Effect": "Allow",
"Action": [
"cloudformation:CancelUpdateStack",
"cloudformation:ContinueUpdateRollback",
"cloudformation:CreateChangeSet",
"cloudformation:DeleteChangeSet",
"cloudformation:DeleteStack",
"cloudformation:DescribeChangeSet",
"cloudformation:DescribeChangeSetHooks",
"cloudformation:DescribeEvents",
"cloudformation:DescribeStackEvents",
"cloudformation:DescribeStackRefactor",
"cloudformation:DescribeStackResource",
"cloudformation:DescribeStackResourceDrifts",
"cloudformation:DescribeStackResources",
"cloudformation:DescribeStacks",
"cloudformation:DetectStackDrift",
"cloudformation:DetectStackResourceDrift",
"cloudformation:ExecuteChangeSet",
"cloudformation:ExecuteStackRefactor",
"cloudformation:GetStackPolicy",
"cloudformation:GetTemplate",
"cloudformation:GetTemplateSummary",
"cloudformation:ListChangeSets",
"cloudformation:ListHookResults",
"cloudformation:ListStackRefactorActions",
"cloudformation:ListStackRefactors",
"cloudformation:ListStackResources",
"cloudformation:RecordHandlerProgress",
"cloudformation:RollbackStack",
"cloudformation:SetStackPolicy",
"cloudformation:SignalResource",
"cloudformation:TagResource",
"cloudformation:UntagResource",
"cloudformation:UpdateStack",
"cloudformation:UpdateTerminationProtection"
],
"Resource": [
"arn:aws:cloudformation:<region>:<account-id>:changeset/LakeSail*",
"arn:aws:cloudformation:<region>:<account-id>:stack/LakeSail*"
]
},
{
"Sid": "AllowIAMConnectionRoleManagement",
"Effect": "Allow",
"Action": [
"iam:GetRole",
"iam:UpdateAssumeRolePolicy",
"iam:UpdateRole",
"iam:UpdateRoleDescription",
"iam:TagRole",
"iam:UntagRole",
"iam:AttachRolePolicy",
"iam:DetachRolePolicy",
"iam:ListAttachedRolePolicies",
"iam:ListRolePolicies",
"iam:ListInstanceProfilesForRole"
],
"Resource": "arn:aws:iam::<account-id>:role/<role-name>"
},
{
"Sid": "AllowIAMStackPolicyManagement",
"Effect": "Allow",
"Action": [
"iam:CreatePolicyVersion",
"iam:DeletePolicyVersion",
"iam:SetDefaultPolicyVersion"
],
"Resource": [
"arn:aws:iam::<account-id>:policy/*<role-name>*",
"arn:aws:iam::<account-id>:policy/lakesail-<connection-id>-RoleBoundary",
"arn:aws:iam::<account-id>:policy/lakesail-<connection-id-lower>-RoleBoundary",
"arn:aws:iam::<account-id>:policy/lakesail-<connection-id>-WorkloadBoundary",
"arn:aws:iam::<account-id>:policy/lakesail-<connection-id-lower>-WorkloadBoundary"
]
},
{
"Sid": "AllowIAMCallbackRoleManagement",
"Effect": "Allow",
"Action": [
"iam:CreateRole",
"iam:DeleteRole",
"iam:GetRole",
"iam:UpdateRole",
"iam:TagRole",
"iam:UntagRole",
"iam:PutRolePolicy",
"iam:GetRolePolicy",
"iam:DeleteRolePolicy",
"iam:ListRolePolicies"
],
"Resource": "arn:aws:iam::<account-id>:role/lakesail-<connection-id>-CallbackRole"
},
{
"Sid": "AllowIAMPassCallbackRole",
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "arn:aws:iam::<account-id>:role/lakesail-<connection-id>-CallbackRole",
"Condition": {
"StringEquals": {
"iam:PassedToService": "lambda.amazonaws.com"
}
}
},
{
"Sid": "AllowLambdaCallbackManagement",
"Effect": "Allow",
"Action": [
"lambda:CreateFunction",
"lambda:DeleteFunction",
"lambda:GetFunction",
"lambda:GetFunctionConfiguration",
"lambda:InvokeFunction",
"lambda:UpdateFunctionCode",
"lambda:UpdateFunctionConfiguration",
"lambda:TagResource",
"lambda:UntagResource",
"lambda:ListTags",
"lambda:AddPermission",
"lambda:RemovePermission"
],
"Resource": "arn:aws:lambda:<region>:<account-id>:function:lakesail-<connection-id>-callback"
}
]
}Callback role and Lambda
The CloudFormation stack creates a single Lambda function, lakesail-<connection-id>-callback, whose only purpose is to post an HMAC-signed webhook to LakeSail at stack create / update / delete events. The Lambda always responds SUCCESS to CloudFormation so the stack is never blocked, even if the callback fails.
Lambda runtime: Python 3.12, arm64, 128 MB memory, 30-second timeout. The function source is embedded in the CloudFormation template; you can audit it by opening the stack in the AWS console.
Trust policy of LakeSailCallbackRole. The role is assumable both by the Lambda service (so the function can run) and by the LakeSail platform principal under the same external-ID condition as the main role (so LakeSail can drive stack-lifecycle operations):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "Service": "lambda.amazonaws.com" },
"Action": "sts:AssumeRole"
},
{
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::921150455437:root" },
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "<external-id>"
}
}
}
]
}Inline permission policy (LambdaLogging):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowLambdaLogging",
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:<region>:<account-id>:log-group:/aws/lambda/lakesail-<connection-id>-callback:*"
}
]
}Inline permission policy (StackInspection). Lets the callback read the connection's own stack and report drift; scoped to this stack only (<stack-name> is the connection's CloudFormation stack):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowStackDescribeAndDrift",
"Effect": "Allow",
"Action": [
"cloudformation:DescribeStacks",
"cloudformation:DescribeStackResource",
"cloudformation:DescribeStackResources",
"cloudformation:DescribeStackResourceDrifts",
"cloudformation:GetStackPolicy",
"cloudformation:DetectStackDrift",
"cloudformation:DetectStackResourceDrift",
"cloudformation:UpdateTerminationProtection"
],
"Resource": "arn:aws:cloudformation:*:<account-id>:stack/<stack-name>/*"
},
{
"Sid": "AllowDriftDetectionStatus",
"Effect": "Allow",
"Action": ["cloudformation:DescribeStackDriftDetectionStatus"],
"Resource": "*"
}
]
}The callback role's only permissions are these: CloudWatch Logs writes to its own log group, and read-only CloudFormation describe / drift-detection on its own stack (plus UpdateTerminationProtection on that stack). It cannot touch any other resource in your account.
Service-linked and IRSA roles created at cluster time
These are created later by LakeSail (using PolicyIAMAndCloudwatch) when you provision the first cluster in a workspace. They are not part of the bootstrap stack.
| Role | Attached managed policies |
|---|---|
| EKS cluster role | AmazonEKSClusterPolicy, AmazonEKSVPCResourceController |
| Node group role | AmazonEKSWorkerNodePolicy, AmazonEKS_CNI_Policy, AmazonEC2ContainerRegistryReadOnly, AmazonEC2ContainerRegistryPullOnly, AmazonSSMManagedInstanceCore |
| Karpenter node role | Same as node group role |
| Karpenter controller IRSA role | Inline policy: EC2 fleet and instance management + IAM instance profile passing |
| EBS CSI controller IRSA role | AmazonEBSCSIDriverPolicy |
| CloudWatch Observability IRSA role | CloudWatchAgentServerPolicy |
| Job-runner IRSA role | Inline policy: scoped S3 access on the connection's workspace bucket; Glue catalog access on glue:* (see note below on the workload boundary) |
| OIDC identity provider (per cluster) | n/a; AWS::IAM::OIDCProvider resource |
| AWS-managed service-linked roles | AWSServiceRoleForAmazonEKS, AWSServiceRoleForAmazonEKSNodegroup, AWSServiceRoleForElasticLoadBalancing, AWSServiceRoleForNATGateway (only created if not already present) |
All LakeSail-created child roles are attached to LakeSailWorkloadBoundary. The iam:CreateRole permission in PolicyIAMAndCloudwatch's IAMRoleBoundary statement is conditioned on this attachment. The workload boundary itself permits glue:* on *; the connection-level policies in your account (PolicyNetworkManage → AllowGlueCatalogManagement) restrict the cross-account role to lakesail*<connection-id>* Glue resources only.
Per-action rationale
Representative subset of the JSON above. Every row is a verbatim Action from the CloudFormation template.
| Action | Resource | Why |
|---|---|---|
eks:CreateCluster | * | EKS does not support resource-level CreateCluster constraints. New clusters are tagged at creation time so subsequent actions can target them by tag. |
eks:Describe*, eks:List* | * (tag-conditioned) plus a small carve-out (ListClusters, DescribeAddonVersions, etc.) for AWS service-listing reads that have no resource-level scoping | Read cluster state. |
eks:CreateNodegroup, :DeleteNodegroup, :UpdateNodegroupConfig | arn:aws:eks:*:<account-id>:nodegroup/lakesail*<connection-id>* | Manage the system node group. |
eks:CreateAddon, :UpdateAddon, :DeleteAddon | Cluster + addon ARNs prefixed lakesail*<connection-id>* | Install VPC CNI, kube-proxy, EKS Pod Identity, CoreDNS, EBS CSI, CloudWatch Observability. |
eks:CreateAccessEntry, :AssociateAccessPolicy | Cluster + access-entry/* ARNs | Grant Karpenter-launched nodes cluster membership. |
eks:CreatePodIdentityAssociation | Cluster + podidentityassociation/* ARNs | Bind pods to IRSA roles. |
autoscaling:* ASG lifecycle (44 actions) | Tag LakeSail-Connection=<connection-id> OR ARN pattern lakesail*<connection-id>* | EKS managed node groups and Karpenter NodePools use ASGs. |
ec2:Describe*, :GetSpotPlacementScores | * | Discover AZs, instance-type capacity, existing VPCs/subnets. Read-only. |
ec2:CreateVpc, :CreateSubnet, :CreateInternetGateway, :CreateNatGateway, :CreateRouteTable, :CreateSecurityGroup, :CreateNetworkAcl, :CreateRoute, :AllocateAddress, :CreateVpcEndpoint | * | Provision the BYOC VPC. Newly created resources are tagged immediately by PolicyNetworkReadAndTag. |
ec2:* modify/delete | arn:aws:ec2:*:<account-id>:*/lakesail*<connection-id>* AND tag LakeSail-Connection=<connection-id> | Modify only LakeSail-tagged VPC objects. Cannot touch your existing infrastructure. |
ec2:RunInstances, :CreateLaunchTemplate(Version), :CreateFleet | * | Launch node group + Karpenter EC2 instances. Instances are tagged on launch. |
elasticloadbalancing:CreateLoadBalancer, :CreateTargetGroup | * with aws:RequestTag/LakeSail-Connection=<connection-id> OR aws:RequestTag/Service=LakeSail | Session-proxy NLB and its target group. |
elasticloadbalancing:CreateListener, :DeleteLoadBalancer, :ModifyTargetGroupAttributes, :RegisterTargets, :DeregisterTargets (20 actions in AllowELBManagement) | Tag LakeSail-Connection=<connection-id> | Configure the session-proxy NLB. |
s3:*, s3express:*, s3tables:*, s3vectors:* | arn:aws:s3:::lakesail*<connection-id>* and /...* | Manage the workspace bucket lakesail-<connection-id>-<network-id>-ws only. |
s3:ListAllMyBuckets | * | Required by S3. No resource-level alternative; LakeSail uses this to enumerate buckets matching the LakeSail prefix. |
glue:GetCatalog, :GetDatabase, :CreateDatabase, :UpdateDatabase, :DeleteDatabase, :TagResource, :UntagResource (plus catalog metadata reads) | arn:aws:glue:*:<account-id>:catalog | Create the Glue catalog database backing each LakeSail catalog. |
glue:* | arn:aws:glue:*:<account-id>:*/lakesail*<connection-id>* | Create/delete tables, partitions, table versions for LakeSail-prefixed databases. |
ssm:DescribeParameters | * | Required by SSM; no resource-level scoping is supported on DescribeParameters. |
ssm:PutParameter, :GetParameter*, :DeleteParameter*, :LabelParameterVersion, :UnlabelParameterVersion | arn:aws:ssm:*:<account-id>:parameter/lakesail*<connection-id>* | Store Konnectivity TLS material as SecureString. |
kms:CreateKey, :CreateAlias, :DeleteAlias, :TagResource | * | Create KMS keys used by LakeSail-provisioned infrastructure. AWS does not support resource-level scoping on kms:CreateKey. |
kms:DescribeKey, :EnableKey, :DisableKey, :GetKeyPolicy, :ListAliases | arn:aws:kms:*:<account-id>:key/* with tag LakeSail-Connection=<connection-id> | Manage only LakeSail-tagged keys. |
acm:RequestCertificate, :ListCertificates | * | Issue session-proxy TLS cert. AWS does not support resource-level scoping on RequestCertificate. |
acm:DescribeCertificate, :DeleteCertificate, :GetCertificate, :AddTagsToCertificate, :RemoveTagsFromCertificate, :ListTagsForCertificate | arn:aws:acm:*:<account-id>:certificate/* | Manage ACM certificates by ARN. |
iam:CreateRole, iam:PutRolePermissionsBoundary | arn:aws:iam::<account-id>:role/lakesail* (requires LakeSail boundary attachment) | Create cluster, node group, IRSA, and Karpenter roles, all forced to attach a LakeSail permissions boundary. |
iam:DeleteRole, :GetRole, :UpdateRole, :UpdateAssumeRolePolicy, :AttachRolePolicy, :PutRolePolicy, etc. | arn:aws:iam::<account-id>:role/lakesail* and arn:aws:iam::<account-id>:role/aws-service-role/* | Manage LakeSail-prefixed roles plus the AWS-managed service-linked roles. |
iam:CreatePolicy, :DeletePolicy, :GetPolicy, :GetPolicyVersion, :ListPolicyVersions, :TagPolicy, :UntagPolicy, :CreatePolicyVersion, :DeletePolicyVersion | arn:aws:iam::<account-id>:policy/lakesail* | Manage policies in the LakeSail namespace only. SetDefaultPolicyVersion is granted only in PolicyCloudFormationAndObservabilityAndIdentity under AllowIAMStackPolicyManagement for *<role-name>* policies plus the four boundary ARNs. |
iam:GetPolicy, :GetPolicyVersion, :ListPolicyVersions | arn:aws:iam::aws:policy/* (read AWS-managed policies) | Resolve AWS-managed policy ARNs that LakeSail attaches to child roles. |
iam:PassRole | arn:aws:iam::<account-id>:role/lakesail* with iam:PassedToService ∈ {eks.amazonaws.com, ec2.amazonaws.com, pods.eks.amazonaws.com} (StringLike) | EKS managed services need to assume LakeSail's cluster, node, and IRSA roles. |
iam:CreateServiceLinkedRole | * with iam:AWSServiceName ∈ {eks.amazonaws.com, eks-nodegroup.amazonaws.com, elasticloadbalancing.amazonaws.com, ec2-nat-gateway.amazonaws.com} (StringEquals) | Service-linked roles for EKS, EKS node groups, ELB, NAT gateway. |
iam:CreateOpenIDConnectProvider, :DeleteOpenIDConnectProvider, :GetOpenIDConnectProvider, :TagOpenIDConnectProvider, :UpdateOpenIDConnectProviderThumbprint, :AddClientIDToOpenIDConnectProvider, :RemoveClientIDFromOpenIDConnectProvider, :ListOpenIDConnectProviderTags, :UntagOpenIDConnectProvider, :ListOpenIDConnectProviders | * | Required to enable IRSA on each cluster. IAM OIDC providers are global; no per-resource scoping. |
iam:GetRole, :UpdateAssumeRolePolicy, :UpdateRole, :AttachRolePolicy, :DetachRolePolicy, etc. | arn:aws:iam::<account-id>:role/<role-name> (the connection role itself) | Allow CloudFormation stack updates to re-tag or update the connection role. |
iam:CreatePolicyVersion, :DeletePolicyVersion, :SetDefaultPolicyVersion | arn:aws:iam::<account-id>:policy/*<role-name>* plus the four boundary ARNs | Allow CloudFormation stack updates to roll new versions of LakeSail's own managed policies. |
iam:CreateRole, :DeleteRole, :GetRole, :UpdateRole, :TagRole, :UntagRole, :PutRolePolicy, :GetRolePolicy, :DeleteRolePolicy, :ListRolePolicies | arn:aws:iam::<account-id>:role/lakesail-<connection-id>-CallbackRole | Manage the callback Lambda's execution role. |
iam:PassRole (callback) | arn:aws:iam::<account-id>:role/lakesail-<connection-id>-CallbackRole with iam:PassedToService=lambda.amazonaws.com | Pass the callback role to Lambda when creating the function. |
cloudformation:ListStacks | * | Detect existing LakeSail stacks during preflight. |
cloudformation:DescribeStacks, :DescribeStackResource, :DescribeStackResources | * | Read top-level state of any stack (needed for cross-stack discovery). |
cloudformation:CreateChangeSet, :UpdateStack, :DeleteStack, :ExecuteChangeSet, :RollbackStack, ... (34 actions in AllowUpdateLakeSailStacks) | arn:aws:cloudformation:<region>:<account-id>:stack/LakeSail* and :changeset/LakeSail* | Reapply or rotate the connection stack. Scoped to LakeSail-prefixed stack names in the deploy region only. |
sts:AssumeRole | arn:aws:iam::921150455437:role/lakesail-*-sp-dns | LakeSail's own DNS role for writing the session-proxy CNAME into LakeSail's proxy.lakesail.com zone, in LakeSail's account, not yours. |
sts:GetCallerIdentity, :DecodeAuthorizationMessage | * | Identity check and authorization debugging. |
servicequotas:ListServiceQuotas, :GetServiceQuota, :GetAWSDefaultServiceQuota, :ListAWSDefaultServiceQuotas, pricing:GetProducts | * | Validate quotas before provisioning; attribute cost. |
cloudwatch:GetMetricData, :GetMetricStatistics, :ListMetrics | * | Read cluster metrics for the LakeSail dashboard. |
logs:CreateLogGroup, :DeleteLogGroup, :DescribeLogGroups, :PutRetentionPolicy, :TagLogGroup, :UntagLogGroup | arn:aws:logs:*:<account-id>:log-group:/aws/eks/lakesail*<connection-id>* | EKS control plane audit log group only. Uses the log-group-specific tagging actions logs:TagLogGroup / :UntagLogGroup. |
lambda:CreateFunction, :DeleteFunction, :GetFunction, :GetFunctionConfiguration, :InvokeFunction, :UpdateFunctionCode, :UpdateFunctionConfiguration, :TagResource, :UntagResource, :ListTags, :AddPermission, :RemovePermission | arn:aws:lambda:<region>:<account-id>:function:lakesail-<connection-id>-callback | Manage the CloudFormation custom-resource callback Lambda only. |
Verifying the deployed role
After the stack reaches CREATE_COMPLETE, you can independently audit the deployed role with these AWS CLI commands.
List the attached managed policies (should match the seven managed policies plus the explicit Deny):
aws iam list-attached-role-policies --role-name <role-name>Inspect the trust policy:
aws iam get-role --role-name <role-name> \
--query 'Role.AssumeRolePolicyDocument'Confirm the permissions boundary:
aws iam get-role --role-name <role-name> \
--query 'Role.PermissionsBoundary'Inspect any of the seven managed policies in full JSON:
POLICY_ARN=$(aws iam list-attached-role-policies --role-name <role-name> \
--query 'AttachedPolicies[?contains(PolicyName, `EKS`)].PolicyArn' --output text)
aws iam get-policy-version \
--policy-arn "$POLICY_ARN" \
--version-id $(aws iam get-policy --policy-arn "$POLICY_ARN" --query 'Policy.DefaultVersionId' --output text)Filter CloudTrail for every action this role has taken:
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=Username,AttributeValue=<role-name>Source
The authoritative source of every policy on this page is the CloudFormation template LakeSail provides for your connection, which you can download pre-filled from your LakeSail console (Settings → Cloud Accounts → Add AWS Account → Advanced → Download Template). The pre-filled version inserts your connection-specific LakeSailConnectionID and LakeSailExternalID; the policy bodies above are identical.