Skip to content

Changes and code

Who made each change and with what tool, which changes are routine, and what manages each asset in infrastructure as code.

Every sync compares what it finds with the sync before, and the change history lists what's different. This page is about reading that history: who made each change and whether by hand, which changes are only values that move on their own, and which of your assets are managed in code. None of it changes anything in your clouds.

Who changed it

Beta

Who changed it is in beta.

Each sync also reads your clouds' own records of the calls made to them since the sync before, and ties every change it found to the calls that made it: who made it, with what tool, and when to the second. It's included in the Starter, Team and Enterprise plans, and reading it costs nothing on any cloud.

CloudRead fromWithThe cloud keeps
AWSCloudTrail event history, write calls only, in each account and region collectedThe discovery role the asset source already has90 days
AzureResource Graph's change history, at the asset source's tenant or subscriptionThe Reader role the asset source's managed identity already has14 days
Google CloudAdmin Activity audit logs, in each project collectedAn optional roles/logging.viewer grant400 days

On AWS and Azure there's nothing to set up. On Google Cloud, grant roles/logging.viewer to the workspace's principal at the project or organization the asset source reads: the connect page has an optional step with the command, and so does the asset source's Permissions tab. Without it, Google Cloud's changes have no author, and everything else works as before.

A new asset source's first sync reads the last 7 days. A change with no call naming its asset in its window shows as unknown: it may be older than what the cloud keeps, or a call the cloud doesn't record. AssetHermit never guesses an author.

Where it shows

  • Changes has a By column, the person or role and the tool. Open a change to see each call that made it, who made it (and through which permission set), when, and a link to the event in your cloud's console.
  • The change feed's filters: Changed by (a name), the tool (Console, CLI and SDK, an IaC tool, a cloud service), and Made by hand. They apply to the last 30 days.
  • Each asset's page shows who made each change, Created by and Last changed by.
  • The inventory has Created by and Changed by columns and facets, and search has $createdBy and $changedBy. An asset keeps up to 10 people and roles who changed it within the workspace's history.
  • Each asset source's Run history has a Who changed it card: what the last sync read, how many changes it attributed, and a switch workspace admins use to stop reading activity for that source.
  • The assistant and MCP clients answer who changed what, and whether by hand.

Names and emails of the people who made changes are visible to everyone who sees the asset, and kept for the workspace's history, in its region.

Made by hand

A change is made by hand when none of its calls came from an infrastructure as code tool, a cloud service or one of your IaC actors. So a change in the console, with the CLI or from a script counts, unless the role that made it is an IaC actor.

IaC actors are the roles, users and identities that deploy from code, such as your CI's role. Workspace admins name them on the workspace settings' Change tracking tab, each one whole or ending in * to match a prefix (github-*), up to 50. Their changes never count as made by hand, past changes included.

On the Notifications tab, workspace admins choose the asset groups to watch for Changed by hand(none by default): after each sync, a notice names who changed those groups' assets by hand. Admins get it in their daily digest, other members in their inbox. See Notifications.

Routine changes

Some values change on their own: last-used dates, counters, etags, autoscaled sizes, lists your cloud returns in a different order. AssetHermit marks these changes routine and leaves them out of the change feed, the dashboard and the assistant, so what shows is what someone changed.

  • Learned in your workspace. A property is learned when it changes in at least 30% of syncs and at least 80% of its changes are timestamps, counters, tokens or reorders. Statuses and text are never learned: a status that keeps changing may be the news. A property learned only from reorders hides only reorders, so a real change to the list still shows. Learned on one asset source, it's routine for that type across the workspace.
  • Hidden, never deleted. "Show routine changes" on the change feed lists them again, with their count. On an asset's page, routine changes in a row fold into one, and routine parts of a change fold inside it.
  • Only updates. Creates and deletes are never routine, and neither are changes to an asset's name, region, tags or relationships. Routine values stay searchable.

Workspace admins decide for themselves too. In an asset's changes, a property's menu has "Ignore changes to this property", for every asset of that type, or "Track this property" on a routine one, which always shows its changes. The workspace settings' Change tracking tab lists what was learned, with how often it changes and its kind of value, and the rules, which win over learning. A rule covers the property and everything under it, such as Indexes[].ItemCount. A workspace can have up to 500 rules; members see them read-only.

To improve what every workspace hides, AssetHermit sees only a learned property's path and how often it changes, with any key you named yourself replaced. Values never leave your workspace.

Infrastructure as code

Each asset gets a record of what manages it in code, by which tool, in which unit and at which address, from what every sync already collects. It's included in the Starter, Team and Enterprise plans, with no new access.

Shown asIn searchMeans
Managed by code$iac.status:managedA unit AssetHermit reads lists it now: a CloudFormation stack, an Azure deployment stack, or a state or manifest from an IaC source.
Managed by a service$iac.status:serviceA cloud service or controller makes and replaces it, such as an Auto Scaling group, GKE or AKS.
Likely managed by code$iac.status:likelyA tag or label a tool sets, cloud activity or one of your conventions says a tool made it, but no unit AssetHermit reads lists it.
Created by the cloud$iac.status:defaultThe provider made it by default: a default VPC, network or security group, a main route table.
No IaC evidence$iac.status:noneNothing AssetHermit can see says what made it. Something may still manage it, in a state it can't read.

Where the tool is known, the app names it: "Managed by Terraform", "Likely managed by CloudFormation". "No IaC evidence" means only that: AssetHermit sees the units it's given, not every one you have. Tools are Terraform, CloudFormation, Bicep, Deployment Manager, Pulumi, Config Connector and Crossplane (Terraform covers OpenTofu, Bicep covers ARM templates); frameworks, where they can be told, CDK, SAM, Serverless, Copilot, StackSet, Service Catalog and Azure Developer CLI.

What says so

CloudSignals
AWS
  • CloudFormation stacks and the resources they list, nested stacks under their root, with CDK construct paths
  • The tags CloudFormation, CDK, SAM, Serverless, Copilot, Service Catalog and Crossplane set
  • The tags Auto Scaling, EKS, Karpenter, Elastic Beanstalk and load balancer controllers set, for what a service makes
  • Default VPCs, subnets, network ACLs, security groups and main route tables
Google Cloud
  • The labels Google's Terraform provider, Infrastructure Manager, Deployment Manager and Config Connector set
  • GKE's, Dataproc's and managed instance groups' labels, for what a service makes
  • The default network, its subnets and its default firewall rules
Azure
  • Deployment stacks and the resources they manage
  • The tags the Azure Developer CLI sets
  • AKS's node resource groups and managed applications, for what a service makes
  • Network Watcher's default instances

On any cloud, Yor's git_* tags say which repository and file a resource comes from, and a create that cloud activity saw an IaC tool make counts as likely managed by it. From a CloudFormation template, AssetHermit keeps only its transforms and CDK construct paths, never the template. No repository is read. On Google Cloud, units come only from IaC sources.

A unit is what a tool applies as a whole: a CloudFormation root stack, an Azure deployment stack, a Terraform state, a manifest. Its page lists its resources by address, each in the inventory, not found, or not a type AssetHermit collects, and its problems.

Coverage and the IaC page

The IaC page, under Inventory, shows coverage: the share of assets expected in code that are managed or likely managed, with the share a unit lists beside it, its trend, and coverage by account, type and group. It lists your units and their problems, and "No IaC evidence" opens those assets in the inventory.

  • Expected in code. Workspace admins choose up to 10 asset groups whose assets belong in code, so sandboxes don't lower coverage. With none chosen, every asset counts. Assets a service or the cloud made aren't counted, nor types code can't manage, such as snapshots, backups and network interfaces.
  • Conventions. Your own rules, a query and a tool, such as $tag:managed-by=terraform → Terraform. An asset a convention matches counts as likely managed by its tool, unless a unit lists it or a service makes it. Up to 20 a workspace; editing one applies at once.
  • Code hosts. Where a unit's code lives, from a manifest or Yor's tags, is a link only on the hosts you list: github.com and gitlab.com by default.

Each asset's page has a Managed by card with its units, address and evidence. The inventory has Managed by and IaC tool facets and columns for status, tool, unit and address, and the dashboard a Managed by code card. In search:

QueryFinds
$changedBy:terraform-*What a pipeline's role changed, by the role's name
$createdBy:~*maria*What someone named Maria created, in any case
$iac.status:none $assetGroup:productionProduction assets with no IaC evidence
$iac.tool:terraform $iac.unit:prod/*Assets in Terraform states whose names start prod/
$iac.framework:cdkWhat a CDK app deployed
$iac.drift:driftedStacks and resources CloudFormation last found drifted

Drift

$iac.drift is CloudFormation's drift as you last detected it: in sync, drifted, or not checked when detection never ran or ran more than 30 days ago. AssetHermit never starts a detection. Two findings come from it: "Stack has drifted from its template" and "Stack is stuck in a failed state".

Changes outside code

  • Changed outside code marks a change made by hand to an asset a unit lists, which the next apply may undo. The change feed's switch of that name lists only those.
  • After each sync, workspace admins are told of changes made by hand to managed assets in the expected scope, and of new assets with no IaC evidence there, with who created them and how. Creates by a cloud service or an IaC actor are left out, and so is a source's first sync.
  • Problems in infrastructure as code: a resource a unit lists that's gone from the cloud, an asset two units claim, entries that couldn't be placed in the inventory, a state not written in 180 days, and a state that couldn't be read whole. Admins are told of new missing and claimed resources once.

IaC sources

Beta

IaC sources is in beta, on request. Ask for access from the Help menu in the app: it opens a support request.

An IaC source gives a workspace read access to where your Terraform and OpenTofu states live, so their resources are managed, not only likely managed. Workspace admins connect one from the workspace settings' IaC tab. It's in the Starter, Team and Enterprise plans, up to 10 sources a workspace.

WhereAccess
Amazon S3, one accountA CloudFormation stack with a role that may list and read only the buckets and prefixes you name, decrypting only through S3
Amazon S3, a whole organizationThe same stack in the management account or a delegated administrator, with a StackSet that puts the role in every account, including those that join later; each account reads its own buckets
Cloud Storage, one bucketroles/storage.objectViewer on the bucket for the workspace's principal, with a condition on the prefixes
Azure Blob Storage, one containerA managed identity from an ARM template, with Storage Blob Data Reader on the container's prefixes

Google Cloud or Azure IaC sources also need access to that cloud's beta.

  • S3 buckets by rule: a bucket's name, or the start of names ending in * (at least 3 characters, such as acme-tfstate-*), each with its prefixes. Up to 10 rules and 50 buckets a source. The connect page suggests buckets from your inventory whose names look like state stores, and for a bucket it holds, the prefixes with states in them, listing only key names.
  • Cloud Storage and Azure: one bucket or container, up to 20 prefixes.
  • What's read: state files (*.tfstate, and the S3 and azurerm backends' other workspaces) and manifests, every hour, only those that changed, up to 2000 files a source and 512 MB a file. Lock files are skipped. Workspace admins can also read a source now.
  • What's kept: of each state and resource, only these fields, and the one attribute that names a resource whose ID isn't an ARN or a full resource name: lineage, serial, terraform_version, mode, type, provider, module, name, index_key, id, arn, self_link. Everything else is skipped as it's read, never decoded: outputs, other attributes, sensitive values. Access keys, key pairs, secret versions and keys are never recorded, not even their address. Only AWS, Google Cloud and Azure providers' managed resources count.
  • Your cloud bills the reads: requests on changed files and transfer between regions. Each source shows what it read; see Cloud read costs.
  • A source that can't be read raises an alert with why, and an S3 source's stack or Azure deployment that's older than the template AssetHermit now writes asks to be updated.

Manifests

Rather not grant read on states? Write a manifest after each apply instead: each resource's address, type and IDs, nothing else, so no secret leaves your CI. The connect page gives the commands that write one from terraform show -json or pulumi stack export in GitHub Actions, GitLab CI or any CI. Copy it as <name>.assethermit-iac.json under a prefix the source reads, and grant read on that prefix only. It's how Pulumi stacks are read, and how a state encrypted with OpenTofu's state encryption can be read.