> For the complete documentation index, see [llms.txt](https://cortex-docs.paloaltonetworks.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://cortex-docs.paloaltonetworks.com/amazon-web-services-manual-onboarding/aws-manual-onboarding-guide/phase-2-provision-the-aws-resources.md).

# Phase 2: Provision the AWS resources

## Phase 2: Provision the AWS resources

This phase provisions the AWS resources used by Cortex to protect your cloud environment.

### Set up your variables

Set these shell variables before running any commands. Use these examples, but replace the placeholder values with the identifiers provided by Cortex for your environment.

```shell
# Identifiers provided by Cortex
OUTPOST_ROLE_ARN="arn:aws:iam::237422644089:role/gcp_saas_role"
AUDIENCE="cortex-audit-logs"
COLLECTOR_SA_ID="116501907218496843752"

# Your AWS environment
AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
AWS_REGION=$(aws configure get region)
CLOUDTRAIL_BUCKET="your-cloudtrail-bucket-name"
CLOUDTRAIL_SNS_ARN="arn:aws:sns:${AWS_REGION}:${AWS_ACCOUNT_ID}:your-cloudtrail-topic"
CLOUDTRAIL_KMS_ARN=""  # The KMS key used by CloudTrail

# Resource names (choose your own naming convention)
SQS_QUEUE_NAME="cortex-cloudtrail-logs-queue"
LOGS_ROLE_NAME="cortex-logs-ingestion-role"
DISCOVERY_POLICY_NAME="Cortex-Discovery-Policy"
CORTEX_ROLE_NAME="CortexPlatformRole"
```

### Step 2.1: Create the Cortex Discovery Custom Policy

Create a custom permission set (IAM managed policy) that gives Cortex read access to AWS services not covered by the standard AWS read-only policies. This includes services like API Gateway, AppSync, Backup, Batch, CodeBuild, GuardDuty, SageMaker, and others.

Use the following to create the policy to be added to the platform role. Name the policy according to the following naming convention: `Cortex-DISCOVERY-Policy-m-a-<lcaas>` where `<lcaas>` is the Cortex tenant ID.

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "apigateway:GET",
        "appsync:GetApiCache",
        "athena:GetCapacityReservation",
        "athena:GetNamedQuery",
        "athena:ListCapacityReservations",
        "athena:ListDatabases",
        "athena:ListDataCatalogs",
        "athena:ListNamedQueries",
        "backup:DescribeFramework",
        "backup:DescribeReportPlan",
        "backup:ListFrameworks",
        "backup:ListReportPlans",
        "backup:ListTags",
        "batch:DescribeSchedulingPolicies",
        "batch:ListSchedulingPolicies",
        "cloudwatch:describeAlarms",
        "codebuild:BatchGetReportGroups",
        "codebuild:ListReportGroups",
        "codedeploy:BatchGetApplications",
        "codedeploy:GetDeploymentConfig",
        "codedeploy:GetDeploymentGroup",
        "codedeploy:ListApplications",
        "codedeploy:ListDeploymentConfigs",
        "codedeploy:ListDeploymentGroups",
        "codedeploy:ListTagsForResource",
        "comprehend:ListEntityRecognizers",
        "comprehend:ListTagsForResource",
        "comprehendmedical:ListEntitiesDetectionV2Jobs",
        "config:DescribeAggregationAuthorizations",
        "connect-campaigns:DescribeCampaign",
        "connect-campaigns:ListCampaigns",
        "controltower:GetLandingZone",
        "controltower:ListLandingZones",
        "controltower:ListTagsForResource",
        "directconnect:DescribeConnections",
        "directconnect:DescribeDirectConnectGateways",
        "directconnect:DescribeVirtualInterfaces",
        "ds:DescribeDirectories",
        "ds:ListLogSubscriptions",
        "ds:ListTagsForResource",
        "ecs:DescribeCapacityProviders",
        "forecast:ListTagsForResource",
        "glue:GetBlueprint",
        "glue:GetBlueprintRun",
        "glue:GetBlueprintRuns",
        "glue:GetMLTransforms",
        "glue:GetSecurityConfigurations",
        "glue:GetTags",
        "glue:ListBlueprints",
        "guardduty:DescribePublishingDestination",
        "guardduty:ListDetectors",
        "guardduty:ListPublishingDestinations",
        "imagebuilder:GetDistributionConfiguration",
        "imagebuilder:GetImage",
        "imagebuilder:GetWorkflow",
        "imagebuilder:ListDistributionConfigurations",
        "imagebuilder:ListImageBuildVersions",
        "imagebuilder:ListImages",
        "imagebuilder:ListWorkflows",
        "kafka:ListClustersV2",
        "lakeformation:DescribeLakeFormationIdentityCenterConfiguration",
        "lakeformation:GetLFTag",
        "lakeformation:ListLFTags",
        "logs:DescribeSubscriptionFilters",
        "logs:GetDataProtectionPolicy",
        "logs:ListTagsLogGroup",
        "memorydb:DescribeSnapshots",
        "memorydb:DescribeSubnetGroups",
        "mq:DescribeConfiguration",
        "mq:ListConfigurations",
        "quicksight:DescribeUser",
        "quicksight:DescribeVPCConnection",
        "quicksight:ListUsers",
        "quicksight:ListVPCConnections",
        "rds:DescribeDBClusterSnapshots",
        "rds:DescribeDBSubnetGroups",
        "rds:DescribeGlobalClusters",
        "rds:ListTagsForResource",
        "redshift-serverless:GetEndpointAccess",
        "redshift-serverless:GetNamespace",
        "redshift-serverless:ListEndpointAccess",
        "redshift-serverless:ListNamespaces",
        "redshift-serverless:ListSnapshots",
        "redshift-serverless:ListTagsForResource",
        "redshift:DescribeClusterSubnetGroups",
        "redshift:DescribeEndpointAccess",
        "sagemaker:DescribeDataQualityJobDefinition",
        "sagemaker:DescribeFeatureGroup",
        "sagemaker:DescribeFlowDefinition",
        "sagemaker:DescribeModelPackageGroup",
        "sagemaker:DescribePipeline",
        "sagemaker:DescribeProject",
        "sagemaker:ListDataQualityJobDefinitions",
        "sagemaker:ListFeatureGroups",
        "sagemaker:ListFlowDefinitions",
        "sagemaker:ListImages",
        "sagemaker:ListModelPackageGroups",
        "sagemaker:ListProjects",
        "sagemaker:ListTags",
        "securityhub:GetFindingAggregator",
        "securityhub:ListFindingAggregators",
        "servicecatalog:DescribePortfolio",
        "servicecatalog:SearchProvisionedProducts",
        "ssm:ListResourceDataSync",
        "workspaces:DescribeTags",
        "workspaces:DescribeWorkspaceDirectories",
        "workspaces:DescribeWorkspaces",
        "xray:GetGroups",
        "xray:GetSamplingRules",
        "xray:ListTagsForResource"
      ],
      "Resource": "*"
    }
  ]
}
```

### Step 2.2: Create the Cortex Platform Role

The Cortex Platform Role is the main IAM role (a set of permissions) that Cortex uses to access your AWS account. The role is configured so that only Cortex is allowed to use it, based on the specific OutpostRoleArn and ExternalID values. This setup relies on "cross-account role assumption," allowing Cortex to run in a different account while safely acting on your behalf in your account.

```shell
# Create trust policy
cat > /tmp/cortex-trust-policy.json << EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "${OUTPOST_ROLE_ARN}"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "sts:ExternalId": "${EXTERNAL_ID}"
        }
      }
    }
  ]
}
EOF

# Create the role
aws iam create-role \
  --role-name "${CORTEX_ROLE_NAME}" \
  --assume-role-policy-document file:///tmp/cortex-trust-policy.json \
  --tags Key=managed_by,Value=paloaltonetworks

# Attach AWS managed policies
aws iam attach-role-policy --role-name "${CORTEX_ROLE_NAME}" \
  --policy-arn "arn:aws:iam::aws:policy/ReadOnlyAccess"
aws iam attach-role-policy --role-name "${CORTEX_ROLE_NAME}" \
  --policy-arn "arn:aws:iam::aws:policy/AmazonMemoryDBReadOnlyAccess"
aws iam attach-role-policy --role-name "${CORTEX_ROLE_NAME}" \
  --policy-arn "arn:aws:iam::aws:policy/SecurityAudit"
aws iam attach-role-policy --role-name "${CORTEX_ROLE_NAME}" \
  --policy-arn "arn:aws:iam::aws:policy/AmazonSQSReadOnlyAccess"
aws iam attach-role-policy --role-name "${CORTEX_ROLE_NAME}" \
  --policy-arn "arn:aws:iam::aws:policy/AWSOrganizationsReadOnlyAccess"

# Attach the custom discovery policy created in Step 1
DISCOVERY_POLICY_ARN="arn:aws:iam::${AWS_ACCOUNT_ID}:policy/${DISCOVERY_POLICY_NAME}"
aws iam attach-role-policy --role-name "${CORTEX_ROLE_NAME}" \
  --policy-arn "${DISCOVERY_POLICY_ARN}"
```

### Step 2.3: Create the SQS Queue for CloudTrail Logs

Create the SQS queue, the "mailbox" in the delivery chain. This queue sits between the CloudTrail SNS topic (the bulletin board) and Cortex (the reader). When CloudTrail saves a new log file to S3, it notifies SNS. SNS forwards that notification to this queue and Cortex picks it up and fetches the log file.

```shell
aws sqs create-queue \
  --queue-name "${SQS_QUEUE_NAME}" \
  --tags managed_by=paloaltonetworks \
  --tags region=<AWS_REGION>

SQS_QUEUE_ARN="arn:aws:sqs:${AWS_REGION}:${AWS_ACCOUNT_ID}:${SQS_QUEUE_NAME}"
SQS_QUEUE_URL=$(aws sqs get-queue-url --queue-name "${SQS_QUEUE_NAME}" --query QueueUrl --output text)
```

### Step 2.4: Set the SQS Queue Policy

By default, the SQS queue (mailbox) does not accept messages from other AWS services. This step adds a permission rule that explicitly allows the CloudTrail SNS topic to put messages into the queue. Without this rule, the SNS → SQS part of the delivery chain would be blocked.

```shell
aws sqs set-queue-attributes \
  --queue-url "${SQS_QUEUE_URL}" \
  --attributes "$(cat <<EOF
{"Policy":"{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"sns.amazonaws.com\"},\"Action\":\"SQS:SendMessage\",\"Resource\":\"${SQS_QUEUE_ARN}\",\"Condition\":{\"ArnEquals\":{\"aws:SourceArn\":\"${CLOUDTRAIL_SNS_ARN}\"}}}]}"}
EOF
)"
```

### Step 2.5: Subscribe the SQS Queue to the CloudTrail SNS Topic

Connect the SQS queue (mailbox) to the CloudTrail SNS topic (bulletin board). After this step, the full delivery chain is active: CloudTrail → S3 Bucket → SNS → SQS. Cortex will start receiving notifications about new log files as soon as the ingestion role (Step 2.6) is created.

```shell
aws sns subscribe \
  --topic-arn "${CLOUDTRAIL_SNS_ARN}" \
  --protocol sqs \
  --notification-endpoint "${SQS_QUEUE_ARN}"
```

### Step 2.6: Create the CloudTrail Logs Ingestion Role

Create the IAM role that Cortex uses to actually read the log files. This role gives Cortex permission to:

* Read log files from the S3 bucket (the storage folder where CloudTrail saves logs).
* Pick up and delete messages from the SQS queue (the mailbox).

This role uses a special trust method called Web Identity Federation (WIF). It allows Cortex's Google Cloud service account to use this AWS role directly, without needing a separate AWS user or password.

```shell
# Create trust policy (web identity federation via Google OIDC)
cat > /tmp/logs-trust-policy.json << EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "accounts.google.com"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "accounts.google.com:oaud": "${AUDIENCE}",
          "accounts.google.com:sub": "${COLLECTOR_SA_ID}"
        }
      }
    }
  ]
}
EOF

# Build inline policy
cat > /tmp/logs-inline-policy.json << EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::${CLOUDTRAIL_BUCKET}",
        "arn:aws:s3:::${CLOUDTRAIL_BUCKET}/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "sqs:ReceiveMessage",
        "sqs:DeleteMessage",
        "sqs:GetQueueAttributes",
        "sqs:ChangeMessageVisibility"
      ],
      "Resource": "${SQS_QUEUE_ARN}"
    },{
      "Effect": "Allow",
      "Action": ["kms:Decrypt"],
      "Resource": "${CLOUDTRAIL_KMS_ARN}"
    }
  ]
}
EOF

# Create the role
aws iam create-role \
  --role-name "${LOGS_ROLE_NAME}" \
  --assume-role-policy-document file:///tmp/logs-trust-policy.json \
  --tags Key=managed_by,Value=paloaltonetworks

# Attach the inline policy
aws iam put-role-policy \
  --role-name "${LOGS_ROLE_NAME}" \
  --policy-name "CloudTrailReadAccessPolicy" \
  --policy-document file:///tmp/logs-inline-policy.json
```

### Step 2.7: Create the Scanner Role (Optional — Outpost Scanning)

If you enabled data security scanning (DSPM), registry scanning, or serverless scanning in the AWS onboarding wizard in Cortex (Phase 1), you must create an additional IAM role that the Cortex scanner assumes. This role has its own trust policy with a separate external ID.

```shell
# Scanner role variables provided by Cortex
SCANNER_PRINCIPAL_ARN='["arn:aws:iam::1234:role/scanner_of_serverless","arn:aws:iam::1234:role/registry_scanner","arn:aws:iam::1234:role/dspm_scanner"]'
# Scanner role name (choose your own naming convention)
SCANNER_ROLE_NAME='cortex-scanner-role'

# Create scanner trust policy
cat > /tmp/scanner-trust-policy.json << EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": ${SCANNER_PRINCIPAL_ARN}
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "sts:ExternalId": "${SCANNER_EXTERNAL_ID}"
        }
      }
    }
  ]
}
EOF

# Create the scanner role
aws iam create-role \
  --role-name "${SCANNER_ROLE_NAME}" \
  --assume-role-policy-document file:///tmp/scanner-trust-policy.json \
  --tags Key=managed_by,Value=paloaltonetworks

# Attach read-only policies (same as platform role)
aws iam attach-role-policy --role-name "${SCANNER_ROLE_NAME}" \
  --policy-arn "arn:aws:iam::aws:policy/ReadOnlyAccess"
aws iam attach-role-policy --role-name "${SCANNER_ROLE_NAME}" \
  --policy-arn "arn:aws:iam::aws:policy/SecurityAudit"
```

### Step 2.8: Additional Permissions (Required).

Additional IAM permissions need to be granted to both the scanner and platform roles in accordance with the security capabilities and features that you enabled in the AWS onboarding wizard in Cortex (Phase 1).

#### Scanner role related permissions

**Serverless scanning**

If you enabled serverless scanning, these policies need to be added to the scanner role:

```json
{
  "Sid": "LAMBDAAccessSid",
  "Effect": "Allow",
  "Action": [
    "lambda:GetFunction",
    "lambda:GetFunctionConfiguration",
    "lambda:GetLayerVersion"
  ],
  "Resource": "*"
}
```

**Registry scanning**

If you enabled registry scanning, these policies need to be added to the scanner role:

```json
{
  "Sid": "ECRAccessSid",
  "Effect": "Allow",
  "Action": [
    "ecr:BatchGetImage",
    "ecr:GetAuthorizationToken",
    "ecr:GetAuthorizationToken"
  ],
  "Resource": "*"
}
```

**Data Security Posture Management (DSPM)**

If you enabled DSPM, this policy must be added to the scanner role. An additional policy must be added to the platform role.

Note that there are two variables in the policy, which must be replaced with the values from the identifiers file that you downloaded from Cortex (Step 1.2): `<MTKmsAccountDSPM>`, and `<CortexPlatformScannerRoleARN>`. The `<AWS_AccountId>` value is the ID of the AWS account you are onboarding (or using as a "host" when onboarding an organizational unit).

```json
{
    "Version": "2012-10-17",
    "Statement": [
{
    "Action": [
"s3:ListBucket",
"s3:GetObject",
"s3:GetBucketLocation",
"s3:GetObjectAttributes"
    ],
    "Resource": [
"arn:aws:s3:::cortex-artifact*",
"arn:aws:s3:::cortex-artifact*/*"
    ],
    "Effect": "Allow"
},
{
    "Action": [
"s3:ListBucket",
"s3:GetObject"
    ],
    "Resource": [
"*"
    ],
    "Effect": "Allow"
},
{
    "Action": [
"kms:DescribeKey",
"kms:Decrypt"
    ],
    "Resource": [
"*"
    ],
    "Effect": "Allow"
},
{
    "Sid": "DescribeAndGenerateKeyWithoutPlaintext",
    "Effect": "Allow",
    "Action": [
"kms:DescribeKey",
"kms:GenerateDataKeyWithoutPlaintext"
    ],
    "Resource": [
"arn:aws:kms:*:<MTKmsAccountDSPM>:key/*"
      ]
},
{
    "Effect": "Allow",
    "Action": [
"iam:PassRole"
      ],
      "Resource": [
  "<CortexPlatformScannerRoleARN>/*"
      ]
},
{
    "Sid": "DynamoDBAccess",
    "Effect": "Allow",
    "Action": [
"dynamodb:DescribeTable",
"dynamodb:Scan"
    ],
    "Resource": [
"arn:aws:dynamodb:*:<AWS_AccountId>:table/*"
      ]
},
{
    "Sid": "CloudWatchAccess",
    "Effect": "Allow",
    "Action": [
"cloudwatch:GetMetricStatistics"
      ],
      "Resource": [
  "*"
      ]
}
    ]
}
```

#### Platform Role Related Permissions

**Agentless disk scanning**

If you enabled agentless disk scanning, add this policy to the platform role. Name the policy according to the following naming convention: `Cortex-ADS-Policy-m-a-<lcaas>` where `<lcaas>` is the Cortex tenant ID.

Note that there are two variables in the policy, which must be replaced with the values from the identifiers file that you downloaded from Cortex (Step 1.2): `<OutpostAccountId>`, `<KmsAccountADS>`.

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ModifySnapshotAttribute",
      "Effect": "Allow",
      "Action": [
        "ec2:ModifySnapshotAttribute"
      ],
      "Resource": [
        "arn:aws:ec2:*::snapshot/*"
      ],
      "Condition": {
        "StringEquals": {
          "ec2:Add/UserId": "<OutpostAccountId>",
          "ec2:ResourceTag/managed_by": "paloaltonetworks"
        }
      }
    },
    {
      "Sid": "DeleteSnapshot",
      "Effect": "Allow",
      "Action": [
        "ec2:DeleteSnapshot"
      ],
      "Resource": [
        "arn:aws:ec2:*::snapshot/*"
      ],
      "Condition": {
        "StringEquals": {
          "ec2:ResourceTag/managed_by": "paloaltonetworks"
        }
      }
    },
    {
      "Sid": "TagSnapshot",
      "Effect": "Allow",
      "Action": [
        "ec2:CreateTags"
      ],
      "Resource": [
        "arn:aws:ec2:*::snapshot/*"
      ],
      "Condition": {
        "StringEquals": {
          "ec2:CreateAction": [
            "CreateSnapshot",
            "CopySnapshot",
            "CreateSnapshots",
            "CopyImage"
          ]
        }
      }
    },
    {
      "Sid": "CreateSnapshotAccessVolume",
      "Effect": "Allow",
      "Action": [
        "ec2:CreateSnapshot"
      ],
      "Resource": [
        "arn:aws:ec2:*:*:volume/*"
      ]
    },
    {
      "Sid": "CreateSnapshot",
      "Effect": "Allow",
      "Action": [
        "ec2:CreateSnapshot"
      ],
      "Condition": {
        "StringEquals": {
          "aws:RequestTag/managed_by": "paloaltonetworks"
        }
      },
      "Resource": [
        "arn:aws:ec2:*::snapshot/*"
      ]
    },
    {
      "Sid": "CopySnapshotSource",
      "Effect": "Allow",
      "Action": [
        "ec2:CopySnapshot"
      ],
      "Condition": {
        "StringEquals": {
          "aws:ResourceTag/managed_by": "paloaltonetworks"
        }
      },
      "Resource": [
        "arn:aws:ec2:*::snapshot/snap-*"
      ]
    },
    {
      "Sid": "CopySnapshotDestination",
      "Effect": "Allow",
      "Action": [
        "ec2:CopySnapshot"
      ],
      "Condition": {
        "StringEquals": {
          "aws:RequestTag/managed_by": "paloaltonetworks"
        }
      },
      "Resource": [
        "arn:aws:ec2:*::snapshot/*"
      ]
    },
    {
      "Sid": "DescribeSnapshots",
      "Effect": "Allow",
      "Action": [
        "ec2:DescribeSnapshots"
      ],
      "Resource": "*"
    },
    {
      "Sid": "DescribeAndGenerateKeyWithoutPlaintext",
      "Effect": "Allow",
      "Action": [
        "kms:DescribeKey",
        "kms:GenerateDataKeyWithoutPlaintext"
      ],
      "Resource": [
        "arn:aws:kms:*:<KmsAccountADS>:key/*"
      ],
      "Condition": {
        "StringLike": {
          "kms:ViaService": "ec2.*.amazonaws.com"
        }
      }
    },
    {
      "Sid": "TargetKeyGrant",
      "Effect": "Allow",
      "Action": [
        "kms:CreateGrant"
      ],
      "Resource": [
        "arn:aws:kms:*:*:key/*"
      ],
      "Condition": {
        "StringLike": {
          "kms:ViaService": "ec2.*.amazonaws.com"
        },
        "Bool": {
          "kms:GrantIsForAWSResource": "true"
        },
        "ForAllValues:StringEquals": {
          "kms:GrantOperations": [
            "Decrypt",
            "Encrypt"
          ]
        }
      }
    },
    {
      "Sid": "ScanningKeyGrant",
      "Effect": "Allow",
      "Action": [
        "kms:CreateGrant"
      ],
      "Resource": [
        "arn:aws:kms:*:<KmsAccountADS>:key/*"
      ],
      "Condition": {
        "StringLike": {
          "kms:ViaService": "ec2.*.amazonaws.com"
        },
        "Bool": {
          "kms:GrantIsForAWSResource": "true"
        },
        "ForAllValues:StringEquals": {
          "kms:GrantOperations": [
            "Encrypt"
          ]
        }
      }
    },
    {
      "Sid": "CreateSnapshotsAccessInstanceAndVolume",
      "Effect": "Allow",
      "Action": [
        "ec2:CreateSnapshots"
      ],
      "Resource": [
        "arn:aws:ec2:*:*:instance/*",
        "arn:aws:ec2:*:*:volume/*"
      ]
    },
    {
      "Sid": "CreateSnapshotsAccessSnapshot",
      "Effect": "Allow",
      "Action": [
        "ec2:CreateSnapshots"
      ],
      "Resource": [
        "arn:aws:ec2:*::snapshot/*"
      ],
      "Condition": {
        "StringEquals": {
          "aws:RequestTag/managed_by": "paloaltonetworks"
        }
      }
    },
    {
      "Sid": "CopyImageAccessImage",
      "Effect": "Allow",
      "Action": [
        "ec2:CopyImage"
      ],
      "Resource": [
        "arn:aws:ec2:*::image/*"
      ]
    },
    {
      "Sid": "CopyImageAccessSnapshot",
      "Effect": "Allow",
      "Action": [
        "ec2:CopyImage"
      ],
      "Condition": {
        "StringEquals": {
          "aws:RequestTag/managed_by": "paloaltonetworks"
        }
      },
      "Resource": [
        "arn:aws:ec2:*::snapshot/*"
      ]
    },
    {
      "Sid": "DescribeImages",
      "Effect": "Allow",
      "Action": [
        "ec2:DescribeImages"
      ],
      "Resource": "*"
    },
    {
      "Sid": "DeregisterImage",
      "Effect": "Allow",
      "Action": [
        "ec2:DeregisterImage"
      ],
      "Resource": [
        "arn:aws:ec2:*::image/*"
      ],
      "Condition": {
        "StringEquals": {
          "ec2:ResourceTag/managed_by": "paloaltonetworks"
        }
      }
    },
    {
      "Sid": "TagImages",
      "Effect": "Allow",
      "Action": [
        "ec2:CreateTags"
      ],
      "Resource": [
        "arn:aws:ec2:*::image/*"
      ],
      "Condition": {
        "StringEquals": {
          "ec2:CreateAction": [
            "CopyImage"
          ],
          "aws:RequestTag/managed_by": "paloaltonetworks"
        }
      }
    }
  ]
}
```

**Automation**

If you enabled automation, this policy must be added to the platform role. Name the policy according to the following naming convention: `Cortex-Automation-Policy-m-a-<lcaas>` where `<lcaas>` is the Cortex tenant ID.

```json
{
"Version": "2012-10-17",
        "Statement": [
          {
            "Sid": "AllAutomationPermissions",
            "Effect": "Allow",
            "Action": [
              "acm:UpdateCertificateOptions",
              "elasticloadbalancing:ModifyLoadBalancerAttributes",
              "rds:AddTagsToResource",
              "rds:CreateTenantDatabase",
              "rds:ModifyDBCluster",
              "rds:ModifyDBClusterSnapshotAttribute",
              "rds:ModifyDBInstance",
              "rds:ModifyDBSnapshotAttribute",
              "rds:ModifyEventSubscription",
              "rds:DescribeDBInstances",
              "s3:PutBucketAcl",
              "s3:PutBucketLogging",
              "s3:PutBucketPolicy",
              "s3:PutBucketPublicAccessBlock",
              "s3:PutBucketVersioning",
              "s3:GetBucketPolicy",
              "s3:GetBucketPublicAccessBlock",
              "s3:GetEncryptionConfiguration",
              "s3:DeleteBucketPolicy",
              "s3:PutObject",
              "s3:GetObject",
              "s3:GetBucketWebsite",
              "s3:GetBucketAcl",
              "s3:DeleteBucketWebsite",
              "s3:PutBucketOwnershipControls",
              "s3:CreateBucket",
              "s3:ListAllMyBuckets",
              "s3:DeleteBucket",
              "s3:ListBucket",
              "ec2:AuthorizeSecurityGroupIngress",
              "ec2:ModifyImageAttribute",
              "ec2:ModifyInstanceAttribute",
              "ec2:ModifyInstanceMetadataOptions",
              "ec2:ModifySnapshotAttribute",
              "ec2:RevokeSecurityGroupEgress",
              "ec2:RevokeSecurityGroupIngress",
              "ec2:CreateSecurityGroup",
              "ec2:DeleteSecurityGroup",
              "ec2:DescribeSecurityGroups",
              "ec2:DescribeInstances",
              "ec2:AuthorizeSecurityGroupEgress",
              "ec2:StartInstances",
              "ec2:StopInstances",
              "ec2:TerminateInstances",
              "ec2:RunInstances",
              "ec2:CreateTags",
              "ec2:CreateSnapshot",
              "ec2:DescribeVpcs",
              "ec2:DescribeSubnets",
              "ec2:DescribeIpamResourceDiscoveries",
              "ec2:DescribeIpamResourceDiscoveryAssociations",
              "ec2:DescribeImages",
              "ec2:CreateNetworkAcl",
              "ec2:GetIpamDiscoveredPublicAddresses",
              "ec2:ModifySubnetAttribute",
              "ec2:ModifyNetworkInterfaceAttribute",
              "ec2:DescribeRegions",
              "ec2:DescribeAddresses",
              "ec2:AllocateAddress",
              "ec2:AssociateAddress",
              "ec2:DisassociateAddress",
              "ec2:ReleaseAddress",
              "ec2:CreateImage",
              "ec2:DeregisterImage",
              "ec2:CopyImage",
              "ec2:MonitorInstances",
              "ec2:UnmonitorInstances",
              "ec2:RebootInstances",
              "ec2:DescribeInstanceStatus",
              "ec2:DescribeIamInstanceProfileAssociations",
              "ec2:GetPasswordData",
              "ec2:DescribeReservedInstances",
              "ec2:DescribeVolumes",
              "ec2:ModifyVolume",
              "ec2:CreateVolume",
              "ec2:AttachVolume",
              "ec2:DetachVolume",
              "ec2:DeleteVolume",
              "ec2:DescribeSnapshots",
              "ec2:DeleteSnapshot",
              "ec2:CopySnapshot",
              "ec2:DescribeLaunchTemplates",
              "ec2:CreateLaunchTemplate",
              "ec2:DeleteLaunchTemplate",
              "ec2:CreateFleet",
              "ec2:DeleteFleets",
              "ec2:DescribeFleets",
              "ec2:DescribeFleetInstances",
              "ec2:ModifyFleet",
              "ec2:DeleteVpc",
              "ec2:CreateVpcEndpoint",
              "ec2:DescribeInternetGateways",
              "ec2:DetachInternetGateway",
              "ec2:DeleteInternetGateway",
              "ec2:DeleteSubnet",
              "ec2:CreateNetworkAclEntry",
              "ec2:DescribeKeyPairs",
              "ec2:AllocateHosts",
              "ec2:ReleaseHosts",
              "ec2:CreateTrafficMirrorSession",
              "cloudtrail:UpdateTrail",
              "cloudtrail:StartLogging",
              "cloudtrail:DescribeTrails",
              "eks:UpdateClusterConfig",
              "eks:DescribeCluster",
              "eks:AssociateAccessPolicy",
              "eks:ListClusters",
              "eks:CreateAccessEntry",
              "eks:UpdateAccessEntry",
              "eks:TagResource",
              "ecs:UpdateClusterSettings",
              "iam:DeleteLoginProfile",
              "iam:GetAccountAuthorizationDetails",
              "iam:GetAccountPasswordPolicy",
              "iam:PassRole",
              "iam:PutUserPolicy",
              "iam:RemoveRoleFromInstanceProfile",
              "iam:UpdateAccessKey",
              "iam:UpdateAccountPasswordPolicy",
              "iam:CreateServiceLinkedRole",
              "kms:CreateGrant",
              "kms:Decrypt",
              "kms:DescribeKey",
              "kms:GenerateDataKey",
              "kms:EnableKeyRotation",
              "lambda:GetFunctionConfiguration",
              "lambda:GetFunctionUrlConfig",
              "lambda:GetPolicy",
              "lambda:InvokeFunction",
              "lambda:UpdateFunctionUrlConfig",
              "lambda:GetFunction",
              "lambda:ListFunctions",
              "lambda:ListAliases",
              "lambda:GetAccountSettings",
              "lambda:ListVersionsByFunction",
              "lambda:DeleteFunctionUrlConfig",
              "lambda:DeleteFunction",
              "lambda:CreateFunction",
              "lambda:PublishLayerVersion",
              "lambda:ListLayerVersions",
              "lambda:DeleteLayerVersion",
              "lambda:UpdateFunctionConfiguration",
              "secretsmanager:CreateSecret",
              "secretsmanager:RotateSecret",
              "secretsmanager:TagResource",
              "ce:GetCostAndUsage",
              "ce:GetCostForecast",
              "ssm:SendCommand",
              "ssm:ListCommands",
              "ssm:ListInventoryEntries",
              "ssm:AddTagsToResource",
              "ssm:RemoveTagsFromResource",
              "ssm:ListTagsForResource",
              "ssm:GetInventory",
              "ssm:ListAssociations",
              "ssm:DescribeAssociation",
              "ssm:ListAssociationVersions",
              "ssm:ListDocuments",
              "ssm:DescribeDocument",
              "ssm:DescribeAutomationExecutions",
              "ssm:GetAutomationExecution",
              "ssm:StartAutomationExecution",
              "ssm:StopAutomationExecution",
              "ssm:CancelCommand",
              "redshift:ModifyCluster",
              "logs:CreateLogGroup",
              "logs:TagResource",
              "logs:CreateLogStream",
              "logs:DeleteLogGroup",
              "logs:DeleteLogStream",
              "logs:FilterLogEvents",
              "logs:DescribeLogGroups",
              "logs:DescribeLogStreams",
              "logs:PutRetentionPolicy",
              "logs:DeleteRetentionPolicy",
              "logs:PutLogEvents",
              "logs:PutMetricFilter",
              "logs:DeleteMetricFilter",
              "logs:DescribeMetricFilters",
              "logs:CreateLogDelivery",
              "logs:GetLogDelivery",
              "logs:UpdateLogDelivery",
              "logs:DeleteLogDelivery",
              "logs:ListLogDeliveries",
              "network-firewall:AssociateFirewallPolicy",
              "network-firewall:CreateFirewallPolicy",
              "network-firewall:DescribeRuleGroup",
              "network-firewall:TagResource",
              "network-firewall:DescribeFirewallPolicy",
              "network-firewall:ListFirewallPolicies",
              "network-firewall:DeleteFirewallPolicy",
              "network-firewall:UpdateFirewallPolicy",
              "network-firewall:DescribeTLSInspectionConfiguration",
              "network-firewall:UpdateFirewallPolicyChangeProtection",
              "network-firewall:CreateFirewall",
              "network-firewall:DeleteFirewall",
              "network-firewall:UpdateFirewallDeleteProtection",
              "network-firewall:DescribeFirewall",
              "network-firewall:ListFirewalls",
              "network-firewall:UpdateFirewallDescription",
              "network-firewall:UpdateSubnetChangeProtection",
              "network-firewall:AssociateSubnets",
              "network-firewall:DisassociateSubnets",
              "network-firewall:CreateRuleGroup",
              "network-firewall:DeleteRuleGroup",
              "network-firewall:ListRuleGroups",
              "network-firewall:UpdateRuleGroup",
              "network-firewall:DeleteResourcePolicy",
              "network-firewall:PutResourcePolicy",
              "network-firewall:DescribeResourcePolicy",
              "network-firewall:ListTagsForResource",
              "network-firewall:UntagResource",
              "network-firewall:DescribeLoggingConfiguration",
              "network-firewall:UpdateLoggingConfiguration"
            ],
            "Resource": "*"
          }
        ]
}
```

Important: When applying this policy, AWS may display a standard alert regarding the use of wildcards (`*`) with the `iam:PassRole` and `iam:CreateServiceLinkedRole` actions. While AWS proactively flags wildcards to encourage specificity, these permissions are safely granted when the Automation security capability is enabled to keep your environment secure.

The Automation capability pre-configures a list of integrations and associated commands to automate security issue responses. Because these commands can be utilized individually or woven into custom playbooks for dynamic issue remediation, Cortex must have the flexibility to provision service-linked roles and pass runtime roles to newly generated security resources on the fly. Since these automated remediation workloads are created dynamically in response to active threats, their exact Resource ARNs cannot be predicted or hardcoded in advance. The entire operational boundary is tightly restricted by the role's trust policy. Only Cortex, verified by your unique ExternalID and OutpostRoleArn, is permitted to trigger these automated guardrails and playbooks on your behalf.

**Data Security Posture Management**

If you enabled DSPM, add this policy to the platform role. An additional policy must be added to the scanner role, as above. Name the policy according to the following naming convention: `Cortex-DSPM-Policy-m-a-<lcaas>` where `<lcaas>` is the Cortex tenant ID.

Note that there are 4 variables in the policy: `MTKmsAccountDSPM`, `CortexPlatformRoleName`, `CortexPlatformScannerRoleName`, `AccountId`.

Note that there are two variables in the policy, which must be replaced with the values from the identifiers file that you downloaded from Cortex (Step 1.2): `<MTKmsAccountDSPM>` and `<CortexPlatformRoleName>`. The `<AWS_AccountId>` value is the ID of the AWS account you are onboarding (or using as a "host" when onboarding an organizational unit).

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Condition": {
        "StringEquals": {
          "aws:ResourceTag/managed_by": "paloaltonetworks"
        }
      },
      "Action": [
        "rds:DeleteDBClusterSnapshot",
        "rds:DeleteDBSnapshot"
      ],
      "Resource": [
        "*"
      ],
      "Effect": "Allow"
    },
    {
      "Action": [
        "rds:AddTagsToResource",
        "rds:CreateDBClusterSnapshot",
        "rds:CreateDBSnapshot",
        "rds:DescribeExportTasks",
        "rds:DescribeDBInstances",
        "rds:DescribeDBClusters",
        "rds:DescribeDBClusterSnapshots",
        "rds:DescribeDBSnapshots",
        "rds:StartExportTask"
      ],
      "Resource": [
        "*"
      ],
      "Effect": "Allow"
    },
    {
      "Action": [
        "s3:PutObject",
        "s3:ListBucket",
        "s3:GetObject",
        "s3:DeleteObject",
        "s3:GetBucketLocation"
      ],
      "Resource": [
        "arn:aws:s3:::cortex-artifact*",
        "arn:aws:s3:::cortex-artifact*/*"
      ],
      "Effect": "Allow"
    },
    {
      "Action": [
        "s3:ListBucket",
        "s3:GetObject",
        "s3:GetObjectAcl"
      ],
      "Resource": [
        "arn:aws:s3:::*"
      ],
      "Effect": "Allow"
    },
    {
      "Sid": "DescribeAndGenerateKeyWithoutPlaintext",
      "Effect": "Allow",
      "Action": [
        "kms:DescribeKey",
        "kms:GenerateDataKeyWithoutPlaintext"
      ],
      "Resource": [
        "arn:aws:kms:*:<MTKmsAccountDSPM>:key/*"
      ]
    },
    {
      "Sid": "TargetKeyGrant",
      "Effect": "Allow",
      "Action": [
        "kms:CreateGrant"
      ],
      "Resource": [
        "arn:aws:kms:*:*:key/*"
      ],
      "Condition": {
        "Bool": {
          "kms:GrantIsForAWSResource": "true"
        }
      }
    },
    {
      "Effect": "Allow",
      "Action": [
        "iam:PassRole"
      ],
      "Resource": [
        "<CortexPlatformRoleARN>/*"
      ],
      "Condition": {
        "StringEquals": {
          "iam:PassedToService": "rds.amazonaws.com"
        }
      }
    },
    {
      "Sid": "DynamoDBAccess",
      "Effect": "Allow",
      "Action": [
        "dynamodb:DescribeTable"
      ],
      "Resource": [
        "arn:aws:dynamodb:*:<AWS_AccountId>:table/*"
      ]
    },
    {
      "Sid": "CloudWatchAccess",
      "Effect": "Allow",
      "Action": [
        "cloudwatch:GetMetricStatistics"
      ],
      "Resource": [
        "*"
      ]
    },
    {
      "Sid": "RedshiftScopedAccess",
      "Effect": "Allow",
      "Condition": {
        "StringEquals": {
          "aws:ResourceTag/managed_by": "paloaltonetworks"
        }
      },
      "Action": [
        "redshift-serverless:DeleteResourcePolicy",
        "redshift-serverless:GetResourcePolicy",
        "redshift-serverless:PutResourcePolicy",
        "redshift:DeleteClusterSnapshot"
      ],
      "Resource": [
        "*"
      ]
    },
    {
      "Sid": "RedshiftUnscopedAccess",
      "Effect": "Allow",
      "Action": [
        "redshift:DescribeClusters",
        "redshift:DescribeClusterSnapshots",
        "redshift:CreateClusterSnapshot",
        "redshift:CreateTags"
      ],
      "Resource": [
        "*"
      ]
    }
  ]
}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://cortex-docs.paloaltonetworks.com/amazon-web-services-manual-onboarding/aws-manual-onboarding-guide/phase-2-provision-the-aws-resources.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
