The scanner runs in your AWS account on ECS Fargate. EventBridge Scheduler starts a coordinator every 15 minutes, and workers scale with the work queue from zero up to 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/aws provider 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

1

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.
2

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.
Choose the profile, the schedule, Max workers and whether to share masked samples, then select Create deployment and enrollment token.
3

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.
4

Apply

aws sts get-caller-identity   # the account you are about to deploy into
terraform init
terraform plan
terraform apply
5

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.
6

Check the first run

The first run reads every store in scope. Its progress, report chunks and any store errors appear in the wizard’s last step and on the deployment’s Runs and Errors tabs.
The module block the wizard generates looks like this:
provider "aws" {
  region = "eu-central-1" # where the scanner runs; it scans every enabled region from here
}

module "tigergate_dspm" {
  source = "https://releases.tigergate.dev/dspm/<version>/tigergate-dspm-aws.zip"

  tigergate_api_url = "https://api.eu.tigergate.dev"
  tigergate_api_key = var.tigergate_api_key # tg_..., your organization's API key
  enrollment_token  = var.enrollment_token  # tgdspm_..., from the console

  vpc_id     = "vpc-0123456789abcdef0"
  subnet_ids = ["subnet-0aaa...", "subnet-0bbb..."] # private subnets with a NAT gateway
  # or: create_vpc = true
}
To keep the token and the key out of Terraform entirely, create the secrets yourself and pass 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

ResourcePurpose
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 serviceFargate and Fargate Spot capacity, plus EC2 when compute = "ec2". Workers rest at zero.
EventBridge Scheduler scheduleStarts the coordinator every 15 minutes (schedule_expression).
SQS queues <prefix>-shards and <prefix>-shards-dlqThe work queue and its dead-letter queue. Both deny non-TLS access.
DynamoDB table <prefix>-stateIncremental scan state, on-demand billing.
Secrets Manager secretsThe 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 workgroupOnly 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.
PolicyCovers
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-contents3: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-contextiam: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.
The policy grants no write, tag, delete, restore or share action on your data, keys or snapshots, no iam:Pass* and no sts:AssumeRole. The only S3 write is to the deployment’s own Athena results bucket. Narrow it with these inputs:
InputDefaultEffect
enable_object_contenttruefalse 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_scanningtrueRead EBS snapshot blocks in place. No volume or copy is created.
enable_database_contenttrueRDS and Aurora, Redshift, DynamoDB, OpenSearch and Athena reads.
enable_file_share_contenttrueEFS and FSx for OpenZFS over NFS, FSx for Windows and ONTAP over SMB.
enable_iam_access_collectiontrueIAM collection, so findings show who can reach each store.
enable_activitytrueCloudTrail reads for data access activity.
enable_ai_inventorytrueBedrock and SageMaker inventory.
scan_regions[]An IAM deny on content reads outside these regions and the home region.

Networking

  • Existing VPC (default): set vpc_id and subnet_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 = true and route_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 to vpc_endpoint_services. The TigerGate API is not an AWS service, so set https_proxy to an egress proxy that allows it. Copy the image to ECR and set scanner_image, because Docker Hub is not reachable. The module’s examples/private-subnets shows 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 in database_users):
    -- PostgreSQL
    CREATE USER tigergate_dspm;
    GRANT rds_iam TO tigergate_dspm;
    -- then grant SELECT on the schemas to classify
    
    On MySQL, create the user IDENTIFIED WITH AWSAuthenticationPlugin. For a database without IAM authentication, store its credentials in a Secrets Manager secret tagged tigergate:dspm:database (any value), or list the secret in database_secret_arns.
  • Network path: the scanner may reach database_ports inside database_cidrs (default: the VPC’s CIDR). Allow the security_group_id output inbound on each database’s security group. A database in another VPC needs peering or a transit gateway route and a matching database_cidrs entry.
  • Redshift: the Data API cannot be limited to reads in IAM, so give the database user SELECT only.
  • 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:fileshare with the file system id as its value, or listed in file_share_secret_arns. Each file system’s security group must allow the scanner’s. FSx for Lustre is not read.
You can also name the secret or the user for a specific database or file system on the deployment’s Configuration tab, under Database access and File shares (EFS and FSx). Each entry names a secret in your account, never a password.

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.
An enrollment token works once. A second account that registers with a token another account already used is refused with enrollment_consumed. Give every account the token of its own deployment.

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_arn output. Otherwise the store fails with kms_denied, and the remediation names the key.
  • Bucket policies that deny: an explicit Deny (including aws:sourceVpce conditions) wins over the role. The store is reported as access_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-scanner tag or its name. The first apply in an account also needs iam:CreateServiceLinkedRole for 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_gib past about 150 million objects.
  • Long lists: a long content_bucket_names, kms_key_arns or database_secret_arns list can push the content policy over IAM’s size limit. Use wildcards such as prod-*.
  • 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 with compute = "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:
curl -fsSLO https://releases.tigergate.dev/dspm/<version>/tigergate-dspm-inaccount.yaml
curl -fsSL  https://releases.tigergate.dev/dspm/<version>/SHA256SUMS | grep inaccount.yaml | sha256sum -c -

aws cloudformation deploy \
  --stack-name tigergate-dspm \
  --template-file tigergate-dspm-inaccount.yaml \
  --capabilities CAPABILITY_IAM \
  --parameter-overrides \
      TigerGateApiUrl=https://api.tigergate.dev \
      TigerGateApiKeySecretArn=arn:aws:secretsmanager:<region>:<account>:secret:tigergate-api-key-AbCdEf \
      EnrollmentTokenSecretArn=arn:aws:secretsmanager:<region>:<account>:secret:tigergate-dspm-token-AbCdEf \
      VpcId=vpc-0123456789abcdef0 \
      SubnetIds=subnet-0aaa,subnet-0bbb
Give the API key as 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_arn output, or apply a new tigergate_api_key with tigergate_api_key_version raised 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_workers changes need a new terraform 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_version raised 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.