Search K
Appearance
Appearance
The CAI-Deploy script helps you automate installation of the AI Security platform and manage its state over time.
You can use CAI-Deploy in different ways:
CAI-Deploy supports deployments for all F5 AI Security products.
Here's a link to the script.
It's configured to deploy on AWS, Azure, and GCP. It assumes you're using Ubuntu Linux 24.04.
If this is your first time using the script, read through this document. Otherwise, jump to Before you deploy.
Before you continue, verify that you have:
kubectl, AWS CLI, Azure SDK, or GCP SDKWe support:
If you create a new Amazon Elastic Kubernetes Service (EKS) cluster, install the AWS Command Line Interface (AWS CLI). Set it up with credentials that can create the required AWS resources, such as the EKS cluster. Install the AWS CLI using the official installer.
To run the installer and deploy AWS resources, the AWS user or role must have the IAM permissions shown in the policies below. The IAM policies are split because they exceed the maximum character limit per policy.
These policies work for:
cai-clustercai-cluster*If you use a different cluster name, update the policies to match.
If you store remote state in Amazon S3, update the bucket name to the state bucket in your AWS account.
With these policies, you can set up permissions to:
If you use this policy, be sure to replace:
YOUR-BUCKET-NAME-HEREYou may also want to specify a specific AWS region and account ID where appplicable, such as for arn:aws:eks:*:*:cluster/cai-cluster
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:DeleteVpc",
"ec2:DeleteSubnet",
"ec2:AttachInternetGateway",
"ec2:DetachInternetGateway",
"ec2:DeleteInternetGateway",
"ec2:ReleaseAddress",
"ec2:DeleteNatGateway",
"ec2:DeleteRouteTable",
"ec2:DisassociateRouteTable",
"ec2:DeleteRoute",
"ec2:DeleteTags",
"ec2:ModifyVpcAttribute",
"ec2:ModifySubnetAttribute"
],
"Resource": "*",
"Condition": {
"StringLike": {
"ec2:ResourceTag/Name": "cai-cluster*"
}
}
},
{
"Effect": "Allow",
"Action": [
"ec2:DescribeImages",
"ec2:DescribeVpcAttribute",
"ec2:DescribeVpcs",
"ec2:DescribeSubnets",
"ec2:DescribeInternetGateways",
"ec2:DescribeAddresses",
"ec2:DescribeNatGateways",
"ec2:DescribeRouteTables",
"ec2:DescribeSecurityGroups",
"ec2:DescribeNetworkInterfaces",
"ec2:DescribeSecurityGroupRules",
"ec2:CreateVpc",
"ec2:CreateSubnet",
"ec2:CreateInternetGateway",
"ec2:AllocateAddress",
"ec2:CreateNatGateway",
"ec2:CreateRouteTable",
"ec2:AssociateRouteTable",
"ec2:CreateRoute",
"ec2:ReplaceRoute",
"ec2:CreateSecurityGroup",
"ec2:CreateTags",
"ec2:RunInstances",
"ec2:RevokeSecurityGroupEgress",
"ec2:AuthorizeSecurityGroupIngress",
"ec2:RevokeSecurityGroupIngress",
"ec2:AuthorizeSecurityGroupEgress",
"ec2:DescribeAddressesAttribute",
"ec2:DisassociateAddress",
"ec2:DeleteSecurityGroup"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"iam:GetPolicy",
"iam:ListAttachedRolePolicies"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"eks:CreateCluster",
"eks:DeleteCluster",
"eks:DescribeCluster",
"eks:UpdateClusterVersion",
"eks:UpdateClusterConfig",
"eks:CreateNodegroup",
"eks:DeleteNodegroup",
"eks:DescribeNodegroup",
"eks:ListClusters",
"eks:TagResource",
"eks:UntagResource",
"eks:CreatePodIdentityAssociation",
"eks:DeletePodIdentityAssociation"
],
"Resource": "arn:aws:eks:*:*:cluster/cai-cluster*"
},
{
"Effect": "Allow",
"Action": [
"eks:DeletePodIdentityAssociation"
],
"Resource": "arn:aws:eks:*:*:podidentityassociation/cai-cluster*"
},
{
"Effect": "Allow",
"Action": [
"eks:CreateAddon",
"eks:DeleteAddon",
"eks:UpdateAddon",
"eks:DescribeAddon",
"eks:DescribeAddonVersions",
"eks:ListAddons",
"eks:DescribePodIdentityAssociation"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"eks:DeleteAccessEntry",
"eks:UpdateAccessEntry"
],
"Resource": [
"arn:aws:eks:*:*:access-entry/cai-cluster*",
"arn:aws:eks:*:*:cluster/cai-cluster*"
]
},
{
"Effect": "Allow",
"Action": [
"eks:CreateAccessEntry",
"eks:DescribeAccessEntry",
"eks:ListAccessEntries"
],
"Resource": [
"*"
]
},
{
"Effect": "Allow",
"Action": [
"ssm:GetParameter",
"ssm:GetParameters",
"ssm:GetParameterHistory"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"autoscaling:UpdateAutoScalingGroup",
"autoscaling:DeleteAutoScalingGroup",
"autoscaling:SetDesiredCapacity",
"autoscaling:TerminateInstanceInAutoScalingGroup"
],
"Resource": "*",
"Condition": {
"StringLike": {
"autoscaling:ResourceTag/Name": "cai-cluster*"
}
}
},
{
"Effect": "Allow",
"Action": [
"autoscaling:CreateAutoScalingGroup",
"autoscaling:DescribeScalingActivities",
"autoscaling:DescribeAutoScalingGroups"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"ec2:CreateLaunchTemplate",
"ec2:DeleteLaunchTemplate",
"ec2:DescribeLaunchTemplates",
"ec2:DescribeLaunchTemplateVersions"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"elasticloadbalancing:DeleteLoadBalancer",
"elasticloadbalancing:DeleteTargetGroup"
],
"Resource": "*",
"Condition": {
"StringLike": {
"elasticloadbalancing:ResourceTag/Name": "cai-cluster*"
}
}
},
{
"Effect": "Allow",
"Action": [
"elasticloadbalancing:CreateLoadBalancer",
"elasticloadbalancing:CreateTargetGroup"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"elasticloadbalancing:CreateListener",
"elasticloadbalancing:DeleteListener",
"elasticloadbalancing:RegisterTargets",
"elasticloadbalancing:DeregisterTargets"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"elasticloadbalancing:Describe*"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"acm:ImportCertificate",
"acm:AddTagsToCertificate",
"acm:RemoveTagsFromCertificate",
"acm:DeleteCertificate"
],
"Resource": "arn:aws:acm:*:*:certificate/cai-cluster*"
},
{
"Effect": "Allow",
"Action": [
"acm:ListCertificates",
"acm:DescribeCertificate"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"ec2:CreateVolume",
"ec2:AttachVolume",
"ec2:DeleteVolume",
"ec2:DescribeVolumes"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::YOUR-BUCKET-NAME-HERE/*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::YOUR-BUCKET-NAME-HERE"
]
},
{
"Effect": "Allow",
"Action": [
"sts:GetCallerIdentity"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"servicequotas:GetServiceQuota",
"servicequotas:ListServiceQuotas",
"servicequotas:ListServices",
"servicequotas:GetAWSDefaultServiceQuota",
"cloudwatch:GetMetricData"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"ec2:DescribeAccountAttributes",
"ec2:DescribeInstanceTypeOfferings",
"ec2:DescribeInstanceTypes",
"ec2:DescribeAvailabilityZones"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"rds:CreateDBCluster",
"rds:CreateDBClusterSnapshot"
],
"Resource": [
"arn:aws:rds:*:*:cluster:cai-cluster*",
"arn:aws:rds:*:*:subgrp:cai-cluster*",
"arn:aws:rds:*:*:cluster-snapshot:cai-cluster*"
]
},
{
"Effect": "Allow",
"Action": [
"rds:DeleteDBCluster",
"rds:ModifyDBCluster",
"rds:DescribeDBClusters",
"rds:CreateDBInstance",
"rds:DeleteDBInstance",
"rds:ModifyDBInstance",
"rds:DescribeDBInstances"
],
"Resource": [
"arn:aws:rds:*:*:cluster:cai-cluster*",
"arn:aws:rds:*:*:db:cai-cluster*"
]
},
{
"Effect": "Allow",
"Action": [
"rds:CreateDBSubnetGroup",
"rds:DeleteDBSubnetGroup",
"rds:ModifyDBSubnetGroup"
],
"Resource": [
"arn:aws:rds:*:*:subgrp:cai-cluster*"
]
},
{
"Effect": "Allow",
"Action": [
"rds:CreateDBParameterGroup",
"rds:DeleteDBParameterGroup",
"rds:ModifyDBParameterGroup"
],
"Resource": [
"arn:aws:rds:*:*:pg:cai-cluster*"
]
},
{
"Effect": "Allow",
"Action": [
"rds:ListTagsForResource",
"rds:DescribeDBSubnetGroups",
"rds:DescribeDBParameterGroups",
"rds:DescribeDBParameters",
"rds:AddTagsToResource",
"rds:RemoveTagsFromResource",
"rds:ListTagsForResource",
"rds:DescribeGlobalClusters"
],
"Resource": [
"*"
]
}
]
}If you use this policy, you may want to include your AWS account ID:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "eks:CreateAccessEntry", "Resource": [ "arn:aws:eks:::cluster/cai-cluster*", "arn:aws:iam:::role/cai-cluster" ] }, { "Effect": "Allow", "Action": [ "iam:DeleteRole", "iam:CreateRole", "iam:PassRole", "iam:AttachRolePolicy", "iam:DetachRolePolicy", "iam:PutRolePolicy", "iam:TagRole", "iam:DeleteRolePolicy", "iam:ListInstanceProfilesForRole" ], "Resource": [ "arn:aws:iam:::role/cai-cluster", "arn:aws:iam:::role/lb-controller" ]
},
{
"Effect": "Allow",
"Action": [
"iam:ListPolicyVersions",
"iam:DeletePolicy",
"iam:CreatePolicy"
],
"Resource":
[
"arn:aws:iam::*:policy/cai-cluster*",
"arn:aws:iam::*:policy/lb-controller*"
]
},
{
"Effect": "Allow",
"Action": [
"iam:ListRolePolicies",
"iam:GetRolePolicy",
"iam:GetUserPolicy",
"iam:ListAttachedUserPolicies",
"iam:GetPolicyVersion",
"iam:GetRole"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"iam:CreateInstanceProfile",
"iam:AddRoleToInstanceProfile",
"iam:RemoveRoleFromInstanceProfile",
"iam:DeleteInstanceProfile",
"iam:GetInstanceProfile"
],
"Resource": "arn:aws:iam::*:instance-profile/cai-cluster*"
}
]
}
If you create a new Azure Kubernetes Service (AKS) cluster, install and set up the Azure command-line interface. Pulumi uses the Azure CLI to authenticate to your account and create resources.
The following command sets up the Azure CLI with a .deb package, which works with Ubuntu. You can set this up on Ubuntu 24.04 LTS.
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bashBefore you can store the Pulumi state in Azure, you need to set the following permissions the user in Azure, on the Storage Container:
Before you create a new Google Kubernetes Engine (GKE) cluster, install and set up the Google Cloud CLI. Next, run the following commands to authenticate.
gcloud auth login
gcloud auth application-default loginNow install the GKE authorization plugin. The following command applies to Debian-based linux systems:
sudo apt-get install google-cloud-sdk-gke-gcloud-auth-pluginNext, to run the installer and deploy all GCP resources, you need to assign permissions / roles to the appropriate GCP user or service accounts. For more information, see the Google Cloud documentation on how to manage access.
You need to set up these accounts to:
For this purpose, set up the following roles:
| Role Name | Role ID |
|---|---|
| Cloud SQL Admin | roles/cloudsql.admin |
| Compute Admin | roles/compute.admin |
| Compute Load Balancer Admin | roles/compute.loadBalancerAdmin |
| Compute Security Admin | roles/compute.securityAdmin |
| Kubernetes Engine Admin | roles/container.admin |
| Project IAM Admin | roles/resourcemanager.projectIamAdmin |
| Service Account Admin | roles/iam.serviceAccountAdmin |
| Service Account User | roles/iam.serviceAccountUser |
| Service Networking Admin | roles/servicenetworking.admin |
| Storage Object Admin | roles/storage.objectAdmin |
| Viewer | roles/viewer |
As listed in assumptions, we assume that you have kubectl installed, configured, and connected to your existing GCP cluster. This allows you to use Pulumi to authenticate to your cluster and create new Kubernetes resources.
To ensure the smoothest installation process possible, ensure you have all information required by the installer, as well as permissions to create needed resources.
Here's a link to the script.
chmod u+x /path/to/script).As shown in the script, it downloads a text-based wizard with the following filename: cai-deploy-latest-linux-x86_64. The options shown on this page reflect the options from that wizard.
The installer can set up a new network. If you plan on using an existing cloud network, be prepared with your VPC ID and subnet IDs.
If you plan on creating a new Kubernetes cluster with the installer and wish for the installer to create a load balancer and Ingress controller, be prepared with a SSL certificate signed by a certificate authority. Do not use self-signed certificates.
If you deploy the platform into an existing cluster, review these options:
moderatorcai-scannerredteamThis depends on the pod that you plan to run on that node. You'll need to run additional commands to include:
The installation script requires some information. As shown in the first few lines of the script, you need to:
aws, azure, or gcp.Given the options, the script includes a large number of prompts. For a full list, see our page on Installer prompts.
After you run the installation script, you'll need to also do the following:
During the deployment process, the installer runs through health checks to ensure that each pod is up and running.
If you're setting up a Red Team deployment, the worker may show an error due to the size of the model downloaded to the container.
For guidance only, we've set up a cost estimate for deploying on AWS.
The following is an estimate. Actual costs will vary based on the specific configuration choices you make during the interactive setup, your usage patterns (traffic, data storage, etc.), and current AWS pricing in your selected region. All prices are based on the us-west-2 (Oregon) region and are subject to change (Pricing per 07/14/2025).
| Service | Estimated Hourly | Estimated Monthly | Notes |
|---|---|---|---|
| EKS Control Plane | 0.10 USD | 73.00 USD | • Fixed cost for AWS Kubernetes control plane |
| EC2 (EKS Worker Nodes) incl. EBS Storage (Defend) | 2.225 USD | 1610 USD | • Based on default instance types and counts (1x t3.xlarge, 1x c7a.4xlarge, 1x m7a.xlarge, 1x g5.xlarge) • Each of the 3 nodes is configured with a 100 GB gp3 root volume |
| EC2 (EKS Worker Nodes) incl. EBS Storage (Red Team) | 2.093 USD | 1532.96 USD | • Based on default instance types and counts (1x g6e.xlarge, 1x m7a.xlarge) • Each of the 3 nodes is configured with a 200 GB gp3 root volume |
| Core Infrastructure Total | 4.418 USD | 3208.96 USD |
| Service | Estimated Hourly | Estimated Monthly | Notes |
|---|---|---|---|
| NAT Gateway | 0.05 USD | 37.35 USD | • Allowing private subnets to access the internet, e.g. pulling images and installing updates • Assumes 100 GB of data processed per month |
| Application Load Balancer (Ingress) | 0.03 USD | 18.77 USD | • Assumes light traffic |
| External Database (RDS Aurora PostgreSQL) | 0.61 USD | 446.04 USD | • 2x db.r7g.large Aurora PostgreSQL DB instances • Assumes 50 GB of storage |
| Optional Resources Total | 0.69 USD | 502.16 USD |
| Estimated Hourly | Estimated Monthly | |
|---|---|---|
| All Resources Total | 3.22 USD | 3,711.12 USD |