max_workers. The scanner reads S3, databases in your VPC, EBS
snapshots, file shares, IAM, Bedrock and SageMaker, and CloudTrail in place. Only findings, classifications, counts,
identifiers and run status leave the account.
Before you start
- Terraform 1.11 or later and the
hashicorp/awsprovider 6.x. Terraform 1.11 adds write-only attributes, which keep the enrollment token and the API key out of Terraform state. - An identity that can apply the module. It creates IAM roles and policies, ECS, SQS, DynamoDB, Secrets Manager,
CloudWatch and EventBridge Scheduler resources, and VPC resources when you set
create_vpc. - An organization API key (
tg_). The wizard can create one. See Before you deploy. - Subnets with a way out. Private subnets with a NAT gateway, or VPC endpoints plus an egress proxy. The scanner needs outbound HTTPS to the TigerGate API host of your region. Nothing connects in.
Deploy with Terraform
Start the wizard
In TigerGate, go to DSPM → Deployments → Add deployment and choose AWS account. The first step shows the
scan policy: the three managed policies (
scan-inventory, scan-content and scan-context) exactly as the
module creates them.Enter the account and network
Enter the name, the 12-digit AWS account id, the Regions to scan (leave empty for every enabled region)
and the network:
- Use my VPC and subnets: the VPC id and private subnet ids. Tick Create VPC endpoints if the subnets have no route to AWS services, and enter their route tables.
- Create a small VPC for the scanner: two private subnets, one NAT gateway, and S3 and DynamoDB gateway endpoints. Databases in your other VPCs are not reachable from it.
Copy the token and the Terraform
Copy the enrollment token. It is shown once. Pick, create or paste the organization API key, or tick the option to
read it from a Secrets Manager secret you created. Copy
main.tf and terraform.tfvars, and keep the tfvars file
out of version control.Register
The coordinator registers on its first tick, within 15 minutes, and posts its preflight checks. To start the tick
now, run the command that
terraform output -raw run_now_command prints. The wizard updates by itself.enrollment_token_secret_arn and tigergate_api_key_secret_arn instead. The API key secret holds the plain key or
JSON {"api_key": "tg_..."}.
What the module creates
| Resource | Purpose |
|---|---|
IAM role <prefix>-scanner-* | The task role of the coordinator and the workers: the scan policy plus the runtime policy. |
Managed policies <prefix>-scan-inventory-*, -scan-content-*, -scan-context-* | The scan policy, split to stay under IAM’s size limit. |
IAM role <prefix>-exec-* | The ECS task execution role: image pull and logs only. It reads no secret. |
IAM role <prefix>-sched-* | Lets EventBridge Scheduler run the coordinator task. |
| ECS cluster, coordinator task and worker service | Fargate and Fargate Spot capacity, plus EC2 when compute = "ec2". Workers rest at zero. |
| EventBridge Scheduler schedule | Starts the coordinator every 15 minutes (schedule_expression). |
SQS queues <prefix>-shards and <prefix>-shards-dlq | The work queue and its dead-letter queue. Both deny non-TLS access. |
DynamoDB table <prefix>-state | Incremental scan state, on-demand billing. |
| Secrets Manager secrets | The enrollment token and the API key (unless you pass existing secrets), and the credential the scanner writes when it registers. |
| CloudWatch log groups and alarms | /tigergate/dspm/<prefix>/coordinator and /worker; two alarms that drive worker scaling. |
| Athena results bucket and workgroup | Only with enable_database_content and enable_athena. Results expire after one day. |
Security group <prefix>-scanner-* | No ingress. Egress is HTTPS, the database ports to database_cidrs and the file share ports to file_share_cidrs. |
Scan permissions
The scan policy is read-only on everything the deployment does not own. A missing grant fails only the matching preflight check and that feature’s stores, and the error names the action.| Policy | Covers |
|---|---|
scan-inventory (always attached) | Inventory, posture and tags of S3, RDS and Aurora, DynamoDB, ElastiCache, Redshift, OpenSearch, EBS volumes and snapshots, EFS, FSx, AWS Backup, Glue, Firehose, DMS, AppFlow, KMS key posture, security groups, and CloudWatch storage metrics. |
scan-content | s3:GetObject and related reads on content_bucket_names; kms:Decrypt limited by kms:ViaService to S3, DynamoDB, Glue, Athena, Secrets Manager and EBS; EBS direct API reads of snapshot blocks; rds-db:connect as the users in database_users; the Redshift Data API; DynamoDB Scan; OpenSearch GET requests; Athena queries in the deployment’s workgroup; database and file share secrets you list or tag. |
scan-context | iam:GetAccountAuthorizationDetails; the users’ credential report (or each user’s access keys and their last use, MFA devices and login profile), for console identities without MFA and stale access; CloudTrail reads, Bedrock and SageMaker inventory. VPC flow log queries only with enable_flow_log_activity. |
iam:Pass* and
no sts:AssumeRole. The only S3 write is to the deployment’s own Athena results bucket.
Narrow it with these inputs:
| Input | Default | Effect |
|---|---|---|
enable_object_content | true | false limits the role to inventory and posture. |
content_bucket_names | ["*"] | Buckets (wildcards allowed) whose objects may be read. |
kms_key_arns | ["*"] | Keys the scanner may decrypt with, through the services above. |
enable_snapshot_scanning | true | Read EBS snapshot blocks in place. No volume or copy is created. |
enable_database_content | true | RDS and Aurora, Redshift, DynamoDB, OpenSearch and Athena reads. |
enable_file_share_content | true | EFS and FSx for OpenZFS over NFS, FSx for Windows and ONTAP over SMB. |
enable_iam_access_collection | true | IAM collection, so findings show who can reach each store. |
enable_activity | true | CloudTrail reads for data access activity. |
enable_ai_inventory | true | Bedrock and SageMaker inventory. |
scan_regions | [] | An IAM deny on content reads outside these regions and the home region. |
Networking
- Existing VPC (default): set
vpc_idandsubnet_ids. Use private subnets with a NAT gateway. create_vpc = true: a /20 VPC with two private and two public subnets, one NAT gateway, and S3 and DynamoDB gateway endpoints.- No internet route: set
create_vpc_endpoints = trueandroute_table_ids. The default endpoints cover the runtime (sts,ecr.api,ecr.dkr,logs,sqs,secretsmanager, plus the S3 and DynamoDB gateways). Add the services you scan tovpc_endpoint_services. The TigerGate API is not an AWS service, so sethttps_proxyto an egress proxy that allows it. Copy the image to ECR and setscanner_image, because Docker Hub is not reachable. The module’sexamples/private-subnetsshows this setup. - Existing interface endpoints: if the VPC already has an interface endpoint with private DNS for a service, leave
that service out of
vpc_endpoint_services, or the apply fails.
Databases and file shares
-
RDS and Aurora: enable IAM database authentication and create a read-only user named
tigergate_dspm(or another name listed indatabase_users):On MySQL, create the userIDENTIFIED WITH AWSAuthenticationPlugin. For a database without IAM authentication, store its credentials in a Secrets Manager secret taggedtigergate:dspm:database(any value), or list the secret indatabase_secret_arns. -
Network path: the scanner may reach
database_portsinsidedatabase_cidrs(default: the VPC’s CIDR). Allow thesecurity_group_idoutput inbound on each database’s security group. A database in another VPC needs peering or a transit gateway route and a matchingdatabase_cidrsentry. -
Redshift: the Data API cannot be limited to reads in IAM, so give the database user
SELECTonly. -
File shares: EFS and FSx for OpenZFS need no credential (NFS, port 2049). FSx for Windows and ONTAP use SMB (port
445) with a read-only user stored in a secret tagged
tigergate:dspm:filesharewith the file system id as its value, or listed infile_share_secret_arns. Each file system’s security group must allow the scanner’s. FSx for Lustre is not read.
Several regions and accounts
One deployment scans every enabled region of its account from its home region. Global services such as S3 are listed once. The console’s region scope chooses what each run reads;scan_regions adds a hard IAM bound that the console
cannot widen. Content in another region is read across regions and billed as inter-region transfer.
Each AWS account is its own deployment. For AWS Organizations, add one deployment per member account in the console,
then deploy one module per account, each with its own enrollment token. The module’s examples/organization uses a
provider alias per account that assumes OrganizationAccountAccessRole. One organization API key serves every
account.
Edge cases
- KMS keys: decryption works when the key policy delegates to IAM. A key whose policy names principals explicitly
must also name the
scanner_role_arnoutput. Otherwise the store fails withkms_denied, and the remediation names the key. - Bucket policies that deny: an explicit
Deny(includingaws:sourceVpceconditions) wins over the role. The store is reported asaccess_denied, never as clean. Add the role to the policy’s exceptions. - Archive storage classes: Glacier Flexible Retrieval and Deep Archive objects need a restore, which the role cannot do. They are reported as unreadable. Glacier Instant Retrieval is read normally.
- Requester Pays: a bucket of another account with Requester Pays shows as
access_denied. - SCPs and permission boundaries: a deny overrides the scan policy, and preflight names the denied action. Exempt
the scanner role by its
tigergate:component = in-account-scannertag or its name. The first apply in an account also needsiam:CreateServiceLinkedRolefor ECS and Application Auto Scaling. - Opted-out or denied regions: they appear in preflight (
regions.enabled) and in the run’s errors. - Very large buckets: with S3 Inventory configured, the coordinator reads the inventory instead of listing. A
listing too large for memory spills to disk at about 120 bytes per object; raise
coordinator_ephemeral_storage_gibpast about 150 million objects. - Long lists: a long
content_bucket_names,kms_key_arnsordatabase_secret_arnslist can push the content policy over IAM’s size limit. Use wildcards such asprod-*. - Customer managed key for the runtime (
kms_key_arn): its key policy must allow the CloudWatch Logs service principal of the region.
Cost
- Idle: the coordinator runs a few seconds every 15 minutes, about 3 USD a month on Fargate. Workers scale to zero. Secrets and alarms add about 2 USD a month.
- Scans: Fargate time while workers run, plus S3 GET and LIST requests on your account. Later runs read only new and changed objects.
use_spot = true: Fargate Spot, or Spot instances withcompute = "ec2". An interrupted shard returns to the queue.compute = "ec2": an Auto Scaling group for estates where Fargate’s limits or price are the constraint.- NAT versus endpoints: the S3 gateway endpoint removes the NAT per-GB charge for same-region object reads. Interface endpoints cost about 7 USD a month each per availability zone.
Deploy with CloudFormation
tigergate-dspm-inaccount.yaml deploys the same runtime and scan policy on Fargate in an existing VPC. CloudFormation’s
console quick-create accepts only templates stored in S3, so deploy it from the CLI:
TigerGateApiKey or TigerGateApiKeySecretArn, and the token as EnrollmentToken or
EnrollmentTokenSecretArn. Exactly one of each is required. TigerGateApiKey and EnrollmentToken are NoEcho, but
CloudFormation keeps them as stack parameters, so the secret ARNs are the safer choice.
Use the Terraform module instead when you need a new VPC, VPC endpoints, EC2 workers, a customer managed key for the
runtime, a list of content buckets (the template takes one ContentBucketPattern), named database or file share
secrets, or separate CloudTrail buckets.
Operate the deployment
- Rotate the API key: write the new key to the secret in the
api_key_secret_arnoutput, or apply a newtigergate_api_keywithtigergate_api_key_versionraised by one. The scanner reads the secret again when TigerGate refuses the old key, so no redeploy is needed. - Change settings: the profile, schedule, scope, shard settings and optional readers are on the deployment’s
Configuration tab. The scanner pulls them on every tick. Network, account and
max_workerschanges need a newterraform apply. - Re-register: if TigerGate rejects the scanner credential, or the scanner lost it, select Re-register on the
deployment’s Overview tab, write the new token to the enrollment token secret (or apply it with
enrollment_token_versionraised by one), and run the coordinator. It registers again with the new token. See The scanner credential is rejected. - Remove: select Revoke on the deployment, then
terraform destroy. Revoking stops the credential; it does not remove the resources in your account.