AWS Setup

Setup tasks for customer-owned AWS accounts

In the scope of an enterprise-level plan, the Webscale Control Plane can provision and manage resources in a customer-provided AWS account. This page describes setup necessary to allow the Control Plane to access an account. It is not necessary when using a plan that includes Webscale-provided AWS accounts.

How It Works

  1. Setup the IAM Permissions Boundary: A customer-managed IAM policy defines the maximum permissions any role created by Webscale can possess. It explicitly denies actions that allow privilege escalation (e.g., creating IAM users, modifying policies without oversight, or creating access keys).

  2. Setup the IAM Role: This is the cross-account role assumed by Webscale. Its policy contains an iam:PermissionsBoundary condition that permits role creation and policy attachment only if the target role has the boundary attached. The role must belong to the same AWS account that the Stack will be provisioned with.

  3. Stacks: Provide the permissions_boundary_arn and the provisioner_role_name as variables when creating a Stack. Stack definitions attach the customer’s boundary ARN to all child IAM roles. Any attempts to assume a role in the customer account without the boundary ARN reference will fail.

CloudFormation Template

The following template is a guideline for creating the IAM Permissions Boundary and IAM Role described in steps 1 and 2 above.

AWSTemplateFormatVersion: '2010-09-09'
Description: "Provisions the Webscale cross-account role and strictly enforces a permissions boundary on all infrastructure deployed by Webscale."

Resources:
  # -------------------------------------------------------------------
  # The Permissions Boundary
  # -------------------------------------------------------------------
  CustomerProvisioningBoundary:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      ManagedPolicyName: WebscaleProvisioningBoundary
      Description: "Maximum allowed permissions for roles provisioned by the Webscale control plane."
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Sid: AllowAppAndInfrastructureServices
            Effect: Allow
            Action:
              - ec2:*
              - eks:*
              - ecr:*
              - elasticloadbalancing:*
              - autoscaling:*
              - logs:*
              - cloudwatch:*
              - secretsmanager:GetSecretValue
              - secretsmanager:DescribeSecret
              - secretsmanager:ListSecretVersionIds
              - secretsmanager:BatchGetSecretValue
              - kms:Decrypt
              - kms:GenerateDataKey*
              - kms:DescribeKey
              - ssm:GetParameter
              - pricing:GetProducts
            Resource: "*"
          - Sid: AllowKarpenterIAMReadsAndPassRole
            Effect: Allow
            Action:
              - iam:ListInstanceProfiles
              - iam:GetInstanceProfile
              - iam:PassRole
              - iam:CreateServiceLinkedRole
            Resource: "*"
          - Sid: ExplicitDenyPrivilegeEscalation
            Effect: Deny
            Action:
              - iam:CreateUser
              - iam:CreateRole
              - iam:CreatePolicy
              - iam:CreateAccessKey
              - iam:CreateLoginProfile
              - iam:PutRolePolicy
              - iam:PutUserPolicy
              - iam:AttachRolePolicy
              - iam:AttachUserPolicy
              - iam:DetachRolePolicy
              - iam:DeleteRolePolicy
              - iam:UpdateAssumeRolePolicy
              - iam:AddUserToGroup
            Resource: "*"

  # -------------------------------------------------------------------
  # The Provisioner Role
  # -------------------------------------------------------------------
  WebscaleCrossAccountRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: AccountProvisioner
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              AWS: "arn:aws:iam::725084300153:root"
            Action: sts:AssumeRole
      Policies:
        - PolicyName: EnforcePermissionsBoundary
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Sid: ReadOnlyActions
                Effect: Allow
                Action:
                  - ec2:Describe*
                  - iam:List*
                  - iam:Get*
                  - eks:Describe*
                  - eks:List*
                  - rds:Describe*
                  - rds:List*
                  - elasticache:Describe*
                  - elasticache:List*
                  - es:Describe*
                  - es:List*
                  - mq:Describe*
                  - mq:List*
                  - secretsmanager:Describe*
                  - secretsmanager:Get*
                  - secretsmanager:List*
                  - route53:Get*
                  - route53:List*
                  - dlm:Get*
                  - ecr:Describe*
                  - ecr:Get*
                  - ecr:List*
                  - kms:DescribeKey
                  - kms:ListGrants
                Resource: "*"

              - Sid: ManageInfrastructure
                Effect: Allow
                Action:
                  - ec2:*
                  - eks:*
                  - rds:*
                  - elasticache:*
                  - es:*
                  - mq:*
                  - secretsmanager:*
                  - route53:*
                  - dlm:*
                  - ecr:*
                  - kms:CreateGrant
                  - kms:RevokeGrant
                  - kms:Decrypt
                  - kms:GenerateDataKey
                  - kms:GenerateDataKeyWithoutPlaintext
                Resource: "*"

              - Sid: IAMRoleCreationWithBoundary
                Effect: Allow
                Action:
                  - iam:CreateRole
                Resource: !Sub "arn:aws:iam::${AWS::AccountId}:role/webscale-*"
                Condition:
                  StringEquals:
                    iam:PermissionsBoundary: !Ref CustomerProvisioningBoundary

              - Sid: IAMRolePolicyModificationsWithBoundary
                Effect: Allow
                Action:
                  - iam:PutRolePolicy
                  - iam:AttachRolePolicy
                  - iam:DetachRolePolicy
                  - iam:DeleteRolePolicy
                  - iam:PutRolePermissionsBoundary
                Resource: !Sub "arn:aws:iam::${AWS::AccountId}:role/webscale-*"
                Condition:
                  StringEquals:
                    iam:PermissionsBoundary: !Ref CustomerProvisioningBoundary

              - Sid: IAMRoleLifecycle
                Effect: Allow
                Action:
                  - iam:DeleteRole
                  - iam:UpdateAssumeRolePolicy
                  - iam:TagRole
                  - iam:UntagRole
                Resource: !Sub "arn:aws:iam::${AWS::AccountId}:role/webscale-*"

              - Sid: IAMInstanceProfileManagement
                Effect: Allow
                Action:
                  - iam:CreateInstanceProfile
                  - iam:DeleteInstanceProfile
                  - iam:AddRoleToInstanceProfile
                  - iam:RemoveRoleFromInstanceProfile
                  - iam:TagInstanceProfile
                  - iam:UntagInstanceProfile
                Resource: !Sub "arn:aws:iam::${AWS::AccountId}:instance-profile/webscale-*"

              - Sid: IAMOIDCProviderManagement
                Effect: Allow
                Action:
                  - iam:CreateOpenIDConnectProvider
                  - iam:DeleteOpenIDConnectProvider
                  - iam:TagOpenIDConnectProvider
                  - iam:UntagOpenIDConnectProvider
                Resource: !Sub "arn:aws:iam::${AWS::AccountId}:oidc-provider/*"

              - Sid: IAMPassRoleRestricted
                Effect: Allow
                Action: iam:PassRole
                Resource: !Sub "arn:aws:iam::${AWS::AccountId}:role/webscale-*"

              - Sid: AllowServiceLinkedRoleCreation
                Effect: Allow
                Action:
                  - iam:CreateServiceLinkedRole
                Resource: !Sub "arn:aws:iam::${AWS::AccountId}:role/aws-service-role/*"
                Condition:
                  StringEquals:
                    iam:AWSServiceName:
                      - "eks.amazonaws.com"
                      - "eks-nodegroup.amazonaws.com"
                      - "elasticloadbalancing.amazonaws.com"

Outputs:
  CrossAccountRoleName:
    Description: "Provide this role name when creating Stacks so the provisioner can assume the role."
    Value: !Ref WebscaleCrossAccountRole

  PermissionsBoundaryArn:
    Description: "Provide this ARN when creating Stacks to include the boundary."
    Value: !Ref CustomerProvisioningBoundary

Have questions not answered here? Contact Support to get more help.

Last modified on September 4, 2026