In the in-account shape the scan runs where your data already is. The scanner
uses an identity you control, reads through the provider’s own API inside your
account, and sends TigerGate a findings document. No object contents, no rows
and no credential cross the boundary.
Get the templates
Every template is in a public repository, so you can read and diff what you are
about to apply before you apply it:
git clone https://github.com/tigergate/tigergate-cloudformation.git
cd tigergate-cloudformation
Deploy from a tag rather than main for anything beyond a first look — a stack
applied from a moving branch changes under you the next time someone runs the
same command:
git clone --branch v1.0.0 https://github.com/tigergate/tigergate-cloudformation.git
Mint an enrollment token
In the console, go to Data Security → Scan Configuration, open the
account, set How this account is scanned to In-account, and mint an
enrollment token.It is shown once. The scanner validates it before enumerating anything, so a
wrong or revoked token fails in milliseconds rather than after a full scan
you would be billed for.
Put the token in your own secret store
No template takes the token as a parameter — a deployment parameter is
readable by anyone who can describe the stack, which is a wider audience
than the people you meant to trust with it. Each template takes a
reference to a secret you own.aws secretsmanager create-secret \
--name tigergate-dspm --secret-string "<token>"
az keyvault secret set \
--vault-name <vault> --name tigergate-dspm --value "<token>"
printf '%s' "<token>" | gcloud secrets create tigergate-dspm --data-file=-
Mirror the image
The scanner task pulls from a registry your own account can reach:docker pull tigergate/tigergate-dspm-agent:1.0.0
docker tag tigergate/tigergate-dspm-agent:1.0.0 <your-registry>/tigergate-dspm-agent:1.0.0
docker push <your-registry>/tigergate-dspm-agent:1.0.0
Both linux/amd64 and linux/arm64 are published. Deploy
Pick your cloud. ContentScanBuckets — and its equivalent on the other two
— is the parameter that matters most: leaving it empty means inventory and
posture only, no object is opened, and the identity the template creates
cannot read one even if asked. Start there.aws cloudformation deploy \
--template-file templates/dspm/aws/in-account.yaml \
--stack-name tigergate-dspm \
--capabilities CAPABILITY_IAM \
--parameter-overrides \
OrganizationId=<from the console> \
ReportEndpoint=https://api.tigergate.dev/api/dspm/reports \
EnrollmentTokenArn=<secrets-manager-arn> \
ScanRegions=us-east-1 \
SubnetIds=<subnet-a>,<subnet-b> \
SecurityGroupId=<sg-id> \
ContentScanBuckets='' \
Schedule='rate(24 hours)'
Creates an ECS cluster, a Fargate task, two IAM roles, a log group and
an EventBridge rule. The subnets need outbound HTTPS to
ReportEndpoint, which is the only destination the scanner needs.az deployment group create \
--resource-group tigergate-dspm \
--template-file templates/dspm/azure/in-account.json \
--parameters \
organizationId=<from the console> \
reportEndpoint=https://api.tigergate.dev/api/dspm/reports \
enrollmentTokenSecretUri=https://<vault>.vault.azure.net/secrets/tigergate-dspm \
contentScanAccounts='' \
scheduleHours=24
Creates a Container Apps job on a user-assigned managed identity. No key
in the template and none to rotate.gcloud deployment-manager deployments create tigergate-dspm \
--template templates/dspm/gcp/in-account.jinja \
--properties "organizationId:<from the console>,\
reportEndpoint:https://api.tigergate.dev/api/dspm/reports,\
enrollmentSecret:projects/<project>/secrets/tigergate-dspm/versions/latest,\
scannerImage:gcr.io/<project>/tigergate-dspm-agent:1.0.0,\
region:us-central1,\
contentScanScope:,\
schedule:0 3 * * *"
Creates a Cloud Run job on a service account made with no key,
authenticating through the metadata server.The same three clouds as modules, if your estate is already Terraform:module "dspm" {
source = "./terraform/dspm/aws" # or /azure, or /gcp
organization_id = "<from the console>"
enrollment_token = var.enrollment_token
scanner_image = "<your-registry>/tigergate-dspm-agent:1.0.0"
subnet_ids = ["subnet-a", "subnet-b"]
security_group_id = "sg-xxxx"
scan_regions = ["us-east-1"]
run_mode = "once" # or "scheduled"
schedule = "rate(24 hours)"
}
run_mode = "once" is the only place a one-time run is a first-class
setting rather than the workaround below. Confirm it works
The first log line proves the token before anything is scanned or billed:[inaccount] enrollment valid: org=… account=…
[inaccount] reporting to https://api.tigergate.dev/api/dspm/reports
Read the second line too — it names the destination, so a stack pointed at
the wrong environment shows up immediately rather than after the findings
land somewhere unexpected.Then in the console, Scan Configuration shows merged / in flight / parked / last merged for the account. last merged: never means nothing has
landed yet.
Run once, or run on a schedule
Both are supported everywhere. A one-time run costs a single task execution and
is the right way to start; scheduled is what production runs.
One time
None of the three clouds has a “no schedule” mode — every template creates a
trigger. So a one-time run is the same trick on each: push the schedule out of
the way, then start the job yourself.
Deploy with Schedule='rate(365 days)', then:aws ecs run-task --cluster tigergate-dspm \
--task-definition tigergate-dspm-scanner --launch-type FARGATE \
--network-configuration \
'awsvpcConfiguration={subnets=[<subnet>],securityGroups=[<sg>],assignPublicIp=ENABLED}'
Deploy with scheduleHours=8760, then:az containerapp job start \
--name tigergate-dspm --resource-group tigergate-dspm
Deploy with schedule:'0 3 29 2 *', then:gcloud run jobs execute tigergate-dspm --region <region>
terraform apply
terraform output run_once_command
Set Expected reporting interval to On demand on the account in the
console when you run this way. Otherwise the console expects a report on a
cadence and reports the account as gone quiet between your runs — a red flag
raised against a deployment doing exactly what you asked of it.
On a schedule
One parameter per cloud, and it is the only thing that changes:
| Cloud | Parameter | Daily | Weekly |
|---|
| AWS | Schedule | rate(24 hours) | rate(7 days) |
| Azure | scheduleHours | 24 | 168 |
| GCP | schedule | 0 3 * * * | 0 3 * * 0 |
| Terraform | run_mode = "scheduled" + schedule | | |
Set the Expected reporting interval on the account to match the schedule
you configured. TigerGate cannot start your scanner, so this is the only thing
that lets the console tell a scanner that stopped from an estate that has not
changed.
Where reports go
Nothing to configure for the US region — it is the default.
tigergate_region = "eu1"
report_endpoint = "https://staging.internal/api/dspm/reports"
An explicit URL wins over the region, and the scanner says so at startup rather
than quietly preferring one. http:// is rejected except on localhost: a
findings document is not your data, but it names every store you hold and what
is wrong with each.
Database access
Relational stores need a database user to connect as. Set it in your deployment —
the console cannot reach a scanner running in your account:
db_user = "tigergate_dspm"
db_secret_arn = "arn:aws:secretsmanager:..."
Prefer IAM database authentication where the engine supports it. There is then
no password to store, rotate or leak.
Sizing and cost
Do not guess, and do not size from a doc. Run once and read the verdict — the
scanner measures the real work and says what it needed:
[inaccount] compute: 167.0 MiB across 24 store(s); about 1m on the current 1 vCPU
The FAQ covers what each profile reads, how the time is
modelled, and why a 5 PB estate is not a 5 PB scan.
When something goes wrong
Troubleshooting is organised by what you
actually see — the scanner not starting, a scan that ran but produced nothing,
and what each coverage state costs you.