Verify & confirm¶
Verification is completed by automated in-product checks and customer-run trust-boundary checks. No message or support action is a completion gate. See Docs authority & product state.
1. Confirm credential readiness¶
Role: Engineer or Admin with connector settings access.
Run automated credential validation in the guided setup. It checks the exact tenant, connector identity, trust condition, resource scope, and provider reachability. A connector cannot advance on a warning or a partially validated credential.
Success evidence: credential state is Validated, with a timestamp and
scope summary.
Recovery: fix the named credential field or trust condition. Rotate the credential if its provenance is uncertain, then rerun validation.
2. Prove the read-only trust boundary¶
Automated credential validation runs the live checks for every cloud: it authenticates as the Venturi identity, runs a positive read probe for each granted service, and confirms that deny-expected writes fail. Positive reads are proven there for AWS, Google Cloud, and Azure alike.
The customer-run check differs by cloud because each module’s local tooling can
reach a different part of the boundary. Run it after terraform apply from the
module directory (infra/<cloud>/onboarding) that you extracted from the pinned
Terraform artifact in guided setup and applied with your terraform.tfvars. Each tab lists the
command, what it checks, and the pass condition.
Run: the role’s trust policy accepts only the generated Venturi
principal, so the module’s scripts/verify.sh, which assumes the role, can
run only under that principal; automated credential validation performs the
live read and denied-write checks from it. From your own account, list every
policy the role holds, then spot-check writes with the IAM policy simulator.
The caller needs iam:, iam:,
iam:GetRolePolicy, and iam:.
ROLE_ARN="$(terraform output -raw role_arn)"
ROLE_NAME="${ROLE_ARN##*/}"
aws iam list-attached-role-policies --role-name "$ROLE_NAME" \
--query 'AttachedPolicies[].PolicyArn' --output json
for POLICY in $(aws iam list-role-policies --role-name "$ROLE_NAME" \
--query 'PolicyNames[]' --output text); do
echo "$POLICY"
aws iam get-role-policy --role-name "$ROLE_NAME" --policy-name "$POLICY" \
--query 'PolicyDocument.Statement' --output json
done
aws iam simulate-principal-policy \
--policy-source-arn "$ROLE_ARN" \
--action-names iam:CreateUser s3:CreateBucket ce:CreateAnomalyMonitor \
cloudwatch:PutMetricData logs:CreateLogGroup cur:PutReportDefinition \
--query 'EvaluationResults[].[EvalActionName,EvalDecision]' \
--output table
Checks: the policy listing is the complete check: it shows every
managed and inline policy on the role, so you can confirm that each
statement allows only the read actions in the
AWS access boundary. The simulator
is a spot check: it evaluates the role’s policies, plus any service control
policies, for the 6 write actions that verify.sh probes, and a policy that
allowed another write action would not show there. Under the Venturi
principal, verify.sh runs a read probe for Cost Explorer, IAM,
Organizations, Price List, CloudWatch metrics, and CloudTrail, plus the CUR
bucket when CUR_BUCKET is set and Bedrock unless SKIP_BEDROCK=1. It does
not probe CloudWatch Logs reads. It attempts the same 6 writes.
Pass: the attached-policy list is []; the inline policies (3 with
Bedrock access enabled, 2 without) contain only Allow statements for the
access-boundary read actions; and no simulator row shows allowed, each
showing implicitDeny or explicitDeny. A verify.sh run that cannot
assume the role exits 2, a successful write exits 1, and a failed read
prints MISS but still exits 0.
Tested identities: the policy listing and the simulator run as your own
IAM caller, and the simulator evaluates the Venturi role named by
role_arn without calling any service as that role. verify.sh and
automated credential validation call each service as the generated Venturi
principal after it assumes the role, so only they test that principal with
live calls.
Incomplete: a verify.sh run from your own account exits 2 because
it cannot assume the role, so it tested no read or write; automated
credential validation supplies that live result. A MISS line from a run
under the Venturi principal still exits 0, but its read stays unproven
until you add the named permission and rerun automated credential
validation.
Run:
export PROJECT_ID="my-prod-project"
gcloud auth login
SERVICE_ACCOUNT_EMAIL="$(terraform output -raw service_account_email)" \
./scripts/verify.sh
The script calls gcloud with the account from gcloud auth login, not
the Application Default Credentials that Terraform uses, so sign in as the
principal that runs the check.
Checks: the service account exists and has no user-managed keys; the
script prints a role: line for each project-scope role binding; a
Workload Identity Pool exists in the project; and a write call, such as
BigQuery dataset creation, made while impersonating the service account is
denied. The script does not list dataset-scope bindings; terraform output
granted_roles summarizes them. The script’s allowlist is broader than the
module: it prints roles/,
roles/, and
roles/ at project scope as OK, with no SEC
line. At project scope, roles/ reads every dataset in
the project, including Vertex AI request-response logging tables, and
either of the other 2 roles lets its holder obtain tokens for service
accounts in the project, including write-capable ones. The allowlist check
therefore does not prove that no write-capable role is bound; the exact
role-line rule below does. The impersonation needs
roles/ on the service account for the
person running the script. To exercise the write probe, grant it for the
check and remove it afterward; without it, the write probe is reported as
SKIP, and automated credential validation runs the denied-write probes as
Venturi’s identity.
Pass: exit 0 with no SEC or MISS lines, and project-scope role
lines that are exactly role: roles/,
role: roles/, and
role: roles/, the project roles the
module grants with billing_ and billing_dataset_id
set. Any other role: line, including roles/,
roles/, or
roles/, is a security finding. A write-probe
SKIP does not fail the check. A security finding the script detects
exits 1, and a missing service account or unreadable IAM policy exits
2. MISS and SKIP lines and allowlisted extra roles still exit 0, so
read the output.
Tested identities: verify.sh reads the service account, its keys, the
project IAM policy, and the Workload Identity Pool as the account from
gcloud auth login. Only its write probe tests the Venturi service account,
by impersonating it. Automated credential validation runs the positive reads
and the denied-write probes as the Venturi identity.
Incomplete: a write-probe SKIP means the script tested no denied write
for the service account; automated credential validation supplies that
result. A MISS line leaves its check unproven until you resolve it and
rerun the script.
Run: while still signed in as the setup operator, capture the Terraform
outputs; a Reader-only identity cannot read Terraform state kept in the
azurerm backend. Then sign in to az as an identity that holds only
Reader on the subscription, not the Owner, User Access Administrator, or
Role Based Access Control Administrator session that ran
terraform apply, and run the checks.
export SUBSCRIPTION_ID="00000000-0000-0000-0000-000000000000"
CLIENT_ID="$(terraform output -raw client_id)"
OBJECT_ID="$(terraform output -raw object_id)"
export CLIENT_ID OBJECT_ID
az login
az account set --subscription "$SUBSCRIPTION_ID"
./scripts/verify.sh
az role assignment list --assignee "$OBJECT_ID" --all --output table
Run az login as the Reader-only identity.
Checks: the service principal exists; each of its role assignments at
subscription scope is an allowlisted read role; a federated identity
credential exists; at most 1 password credential exists; and 3 write
probes are denied (a Contributor role assignment for the service principal,
a resource group, and an action group). The write probes run as the
identity signed in to az, not as the service principal. From the
Reader-only identity they are always denied, so they test only that
identity and prove nothing about the service principal. The service
principal’s boundary is proven by the --all listing, which shows its role
assignments at every scope, and by automated credential validation, which
runs its denied-write probes as the service principal. The script’s
allowlist is not that proof: it checks subscription scope only, and it also
accepts roles the module never grants, including Reader and Data Access,
which can read and write all data in a storage account through its account
keys, and Billing Reader.
If you run the script from a privileged session instead, its write probes
can succeed. Under an Owner session, the role-assignment and resource-group
probes succeed: the script reports 2 security findings, removes the
Contributor assignment it created, and leaves a
venturi-verify-must-fail-<timestamp> resource group for you to delete.
Under a User Access Administrator or Role Based Access Control
Administrator session, only the role-assignment probe succeeds: the script
reports 1 security finding, removes the assignment, and creates no resource
group.
With APIM or Event Hubs access enabled and its resource ID set, the
workspace-scope Log Analytics Reader or namespace-scope Azure Event Hubs
Data Receiver assignment sits below the subscription, so the script does
not list it; the --all listing shows it with its scope. If the resource
ID is empty, the module assigns the role at subscription scope. The script
accepts Log Analytics Reader there without a finding, although at that
scope it reaches every workspace in the subscription, and it reports Azure
Event Hubs Data Receiver as outside its allowlist.
Pass: exit 0 with no SEC or MISS lines; with APIM access
enabled, no role: Log Analytics Reader line; and an --all listing that
shows only Reader, Cost Management Reader, and Monitoring Reader on the
subscription, plus Log Analytics Reader on the named workspace and Azure
Event Hubs Data Receiver on the named namespace when those grants are
enabled. A security finding exits 1, and a missing service principal or
unreadable role assignment list exits 2. In the client-secret fallback, a
MISS line for the absent federated credential is expected; resolve every
other MISS.
Tested identities: verify.sh and the --all listing run as the
Reader-only identity signed in to az. The listing reads the service
principal’s role assignments, and the script’s write probes exercise the
Reader-only identity alone. Automated credential validation runs the
denied-write probes as the service principal.
Incomplete: the script’s denied write probes leave the service
principal’s write boundary unproven; the --all listing and automated
credential validation supply it. Any MISS line other than the expected
client-secret fallback line leaves its check unproven until you resolve it
and rerun the script.
Success evidence: automated credential validation passes its positive reads and denied writes, the customer-run check for your cloud meets its pass condition, and every deny-expected write leaves provider state unchanged. Record which identity ran each check. A result listed as incomplete leaves that part of the boundary unproven until the check that the tab names for it passes.
Recovery: remove any write grant immediately. For a failed read, add only the named permission at the narrowest resource scope, then rerun the failed probe and the complete boundary check. Troubleshooting maps each result to its fix.
3. Inspect attribution evidence¶
Role: Engineer or authorized viewer with /invocations access.
Open /invocations and inspect the 1st AttributionRecord produced from the
connected source or accepted provider export file. The surface shows only
records inside the signed-in user’s role scope, so record the user and role
that run this check. An event accepted by the ingestion API
(202 Accepted) or recorded by the proxy appears there
within approximately 30 seconds.
Confirm:
- source and evidence lineage;
- identity and cost mapping;
- coverage and explicit unknowns;
- source and record freshness;
- confidence and export eligibility.
Success evidence: the record is visible and its evidence links resolve to the accepted source or file. This is the engineering active-use milestone. The check is incomplete when no record from the source appears or when the source sits outside the checking role’s scope; an incomplete check confirms neither active use nor a source failure.
Recovery: follow the record’s missing-evidence, unknown, or stale state back to the named provider, identity, cost-mapping, or deployment step. Do not replace an unknown with an unsupported value.
4. Verify persona completion¶
Persona-complete production onboarding is a separate gate. Product, Security, Engineering, and Finance must each complete real in-product actions. Finance completion requires acceptance of a chargeback-eligible export. There is no admin or support override.
Use the Enterprise readiness checklist for the required evidence. Support remains an optional recovery path.
Sign in to send feedback. Opens in a new tab.
Copy page details
Docs feedback: Verify & confirm
Page: https://docs.venturi.systems/reference/verification/