Using Cirro and CirroDash¶
This page is the repeatable tool workflow for the lab. You will run it more than once as your identity and available evidence change:
Azure login -> Cirro collection -> SQLite artifact -> Cirro ingestion
-> Neo4j -> CirroDash investigation
1. Check the workshop tools¶
Open a terminal in the workshop environment and confirm that the required commands are available:
Use the binaries supplied by the instructor. If a command is missing or the available options differ from this guide, stop and ask an instructor before installing a different release.
Create a directory for your lab artifacts and keep all collected data there:
Sensitive artifacts
Cirro SQLite databases can contain tenant metadata and data-plane values. Keep this directory local to the workshop system, do not commit it, and remove it when instructed at the end of the lab.
2. Authenticate to the correct tenant¶
Clear any previous Azure CLI session, then authenticate with the identity for the current lab stage:
az logout
az login \
--tenant <workshop-tenant-id> \
--username <your-user-principal-name> \
--allow-no-subscriptions
az account show --output table
Before collecting, verify all three of these values:
- the active tenant is the workshop tenant;
- the signed-in user is the intended guest identity; and
- the active subscription is the workshop subscription, when that identity has subscription access.
An initial low-privilege guest may not have a visible subscription. That is an expected observation during the first collection.
3. Collect with Cirro¶
Run Cirro using the authenticated Azure CLI session:
Cirro writes the normalized collection to cirro_output.db. Confirm that the
file exists and contains tables before continuing:
Make a stage-specific copy so a later collection does not erase your evidence:
Use names such as initial-guest.db, defcon-reader.db, and
key-vault-data.db throughout the lab.
If collection returns less data than expected
Recheck az account show, confirm the identity's current access, and run
the collection again. Dynamic group membership and new role access may
take several minutes to propagate.
4. Inspect before ingesting¶
The SQLite artifact is evidence as well as graph input. A quick inspection helps distinguish a successful but low-privilege collection from a failed one:
sqlite3 cirro_output.db '.tables'
sqlite3 cirro_output.db \
"SELECT resource_type, COUNT(*) FROM resources GROUP BY resource_type ORDER BY COUNT(*) DESC LIMIT 15;"
If the resources table is absent during the first guest collection, inspect
the identity tables that are present instead. Do not edit the database.
5. Ingest into Neo4j¶
Use the Neo4j connection values supplied by the instructor. The common local workshop form is:
cirro graph ingest \
--type az \
--file cirro_output.db \
--server bolt://localhost:7687 \
--user neo4j \
--password <workshop-neo4j-password>
Look for a successful completion message with no connection or schema errors. If ingestion fails, do not repeatedly recollect Azure data—the SQLite artifact already exists. Fix the Neo4j connection and ingest the same file again.
Refreshing the graph
Ingest each new stage-specific collection as the lab progresses. Cirro uses stable object identifiers to connect new evidence to existing nodes.
6. Connect CirroDash¶
Open the CirroDash URL supplied by the instructor. On the connection screen, enter the Neo4j settings used for ingestion:
| Field | Common local value |
|---|---|
| Scheme | bolt |
| Server | localhost |
| Port | 7687 |
| Username | neo4j |
| Password | instructor-provided password |
If CirroDash runs in a container, localhost may refer to that container
rather than your host. Use the server name supplied by the instructor in that
case.
After connecting:
- Open a preconfigured identity or resource table.
- Confirm that rows appear and that the most recent identity is present.
- Create a tab named Workshop Investigation.
- Add a Count card named Total nodes with this query:
- Add a Table card named Node types with this query:
Use Test Query before saving each card. These two cards provide a quick check that later ingestion actually changes the graph.
7. Investigate without getting lost¶
For each lab stage, use the same sequence:
- Find the known starting object, usually your current user.
- Inspect its properties and copy its stable identifier into your notes.
- Follow one relationship at a time.
- Record the relationship verb and the destination object.
- Compare the path with the raw SQLite evidence when a relationship is unclear.
- Save useful Cypher as a CirroDash table card.
A generic search card can help locate a known display value without assuming a specific node label:
MATCH (n)
WHERE any(value IN [n.displayName, n.userPrincipalName, n.name]
WHERE toLower(coalesce(value, '')) CONTAINS toLower('<search-text>'))
RETURN labels(n) AS labels, n.displayName, n.userPrincipalName, n.name, n.id
LIMIT 50
Replace <search-text> with a non-secret value such as part of your user
principal name or vm-cocoaman-diagnostics.
Troubleshooting checklist¶
| Symptom | Check |
|---|---|
az login reaches the wrong tenant |
Log out and repeat login with the workshop tenant ID |
| No subscription appears | Confirm the current identity and allow time for dynamic membership |
cirro_output.db is missing |
Review the Cirro error and verify the working directory is writable |
| SQLite has identity data but no resources | The current identity may not yet have subscription visibility |
| Neo4j connection is refused | Confirm Neo4j is running and verify scheme, host, and port |
| CirroDash connects but shows no rows | Ingest the database, refresh the card, and verify the selected Neo4j database |
| A query reports an unknown property | Inspect a returned node first; Azure object types do not all share the same properties |
For command options outside this workshop, consult the Cirro documentation.