ESEN

Dictionary

Which resource in each provider plays the same part, and when it isn't 1:1. Every name is checked in CI against the real schema of azurerm ~> 5.8, aws ~> 6.67 and google ~> 8.6.

Grouping of accounts/subscriptions/projects

1:1Concept: resource-hierarchy

Account / subscription / project

Not 1:1Concept: resource-hierarchy

azurerm_subscription creates an alias for a subscription and needs a billing scope; the resource doesn't "create" the tenant relationship. In GCP, besides creating the project, each API is enabled separately (google_project_service).

↗ registry.terraform.io↗ registry.terraform.io

Resource container inside the account

No equivalentConcept: resource-hierarchy

AWS

No direct equivalent

GCP

No direct equivalent

An Azure resource group owns the lifecycle of its resources (deleting it deletes them). In AWS, aws_resourcegroups_group is a tag- or stack-based query, not a container; in GCP the closest container is the project itself.

↗ learn.microsoft.com↗ registry.terraform.io

Enabling services before use

No equivalent

In GCP each API is enabled per project and a terraform apply on a new project fails until it is. In Azure the provider registers the resource providers it needs automatically unless you turn that off. AWS has no per-service equivalent step.

↗ registry.terraform.io↗ registry.terraform.io

Organization-level guardrails

Not 1:1Capability: governance-guardrails

They limit different things: Azure Policy evaluates resource properties (and can audit, deny or modify), AWS SCPs cap IAM actions, and GCP org policies apply predefined or custom constraints. Definition and assignment are separate resources in Azure and AWS.

↗ learn.microsoft.com↗ aws.amazon.com↗ cloud.google.com

Workload identity

Not 1:1Capability: workload-identity

aws_iam_role bundles identity, trust policy and (with attached policies) permissions. In Azure and GCP the identity is one resource and permissions are separate role assignments or bindings.

Granting permissions

Not 1:1Capability: access-control

In GCP every resource has three variants: _iam_policy (authoritative for the whole policy), _iam_binding (authoritative per role) and _iam_member (additive). Mixing an authoritative one with _iam_member on the same resource makes them fight on every apply. In Azure the scope lives on the role assignment itself.

↗ registry.terraform.io

Custom role or policy

Not 1:1Capability: access-control

An Azure or GCP custom role is a list of actions later assigned on a scope. An AWS policy is a document that can include conditions and specific resources, and it's attached to an identity.

OIDC federation (CI/CD, another cloud)

Not 1:1Capability: external-identity-federation

In Azure each credential is an exact issuer + subject pair on an identity. In AWS the provider is one per URL per account, and trust lives in the role's trust policy. In GCP the pool and provider carry the CEL condition, and access is granted with bindings on a principalSet.

Virtual network

Not 1:1Capability: virtual-networkConcept: network-scope

The VNet and the AWS VPC are regional; the GCP VPC is global and its subnets are regional.

Subnet

Not 1:1Capability: virtual-networkConcept: network-scope

aws_subnet lives in a single availability zone (availability_zone); the Azure subnet spans the region and the GCP one is regional too. High availability in AWS = one subnet per AZ.

Traffic filtering

Not 1:1Capability: network-filtering

The NSG is associated with subnets or NICs. The AWS security group attaches to network interfaces and is stateful (NACLs are per subnet and stateless). In GCP rules belong to the VPC and target instances by network tags or service accounts.

Routes

Not 1:1Capability: virtual-network

Azure and AWS associate a route table with each subnet. GCP has no per-subnet table: each route is a VPC resource and can target instances by network tags.

Network peering

Not 1:1Capability: virtual-network

In Azure and GCP you need one resource per side of the peering. In AWS it's one connection the other side accepts (aws_vpc_peering_connection_accepter for another account or region).

Internet egress with NAT

Not 1:1Capability: virtual-network

In Azure the NAT gateway is associated with the subnet. In AWS it lives in a public subnet and private subnets reach it via a route. In GCP Cloud NAT is a configuration on a Cloud Router.

Private access to a managed service

Not 1:1Capability: private-service-access

aws_vpc_endpoint covers the Interface and Gateway types (vpc_endpoint_type). In GCP it depends on the service: a Private Service Connect endpoint is a forwarding rule, and Cloud SQL's private IP uses private services access (google_service_networking_connection).

Private DNS zone

Not 1:1Capability: private-dns

In Azure the private zone is its own resource type and is linked to each VNet. In AWS and GCP it's the same resource as a public zone, with a vpc block (AWS) or visibility = private (GCP).

Hybrid DNS forwarding

Not 1:1Capability: dns-forwarding

Azure and AWS model inbound and outbound endpoints. In GCP inbound is a server policy and outbound is a forwarding_config block inside a managed zone.

Managed firewall (the instance)

Not 1:1Capability: managed-firewall

Azure Firewall is a resource deployed into the VNet (in its own subnet) and a separate policy holds its rules. Network Firewall creates one endpoint per availability zone in the subnets you give it and the route tables must point at it. In GCP the firewall endpoint is zonal and is associated with each VPC; it inspects nothing until a network firewall policy rule with the apply_security_profile_group action sends it traffic (see firewall-rules).

↗ learn.microsoft.com↗ aws.amazon.com↗ cloud.google.com

Managed firewall rules (incl. FQDN filtering)

Not 1:1Capability: egress-fqdn-filtering

In Azure rules live in collection groups of a firewall policy, and FQDN rules can be application or network rules. In AWS domain filtering is a stateful rule group (later referenced from the firewall policy) and Network Firewall uses Suricata. In GCP rules belong to a network firewall policy associated with the VPC, and FQDN objects are a Standard-tier capability.

↗ learn.microsoft.com↗ aws.amazon.com↗ cloud.google.com

Network transit hub

Not 1:1Capability: virtual-network

These are the alternatives to peering when you want transit between spokes: Virtual WAN (the hub is a Microsoft-managed network with its own router), Transit Gateway (attachments with one route table per association and explicit propagation) and Network Connectivity Center (global hub with spokes; VPC spokes exchange subnet routes). The pattern's modules use peering in Azure and GCP (not transitive) and Transit Gateway in AWS: they are not the same topology.

↗ learn.microsoft.com↗ aws.amazon.com↗ cloud.google.com

Object storage

Not 1:1Capability: object-storage

Azure has one more level: the storage account (network, Shared Key, encryption) with containers inside. In the AWS provider bucket configuration is split into separate resources (aws_s3_bucket_versioning, _public_access_block, _lifecycle_configuration…). In GCP almost everything is a block on the bucket.

↗ registry.terraform.io

Object expiration

Not 1:1Capability: object-lifecycle

In GCP it isn't a separate resource but a lifecycle_rule block inside google_storage_bucket.

Managed PostgreSQL

1:1Capability: managed-postgres

For Aurora PostgreSQL on AWS the resource is aws_rds_cluster (with aws_rds_cluster_instance).

Secrets

Not 1:1Capability: secrets-store

Key Vault is a container with its own access model, and secrets live inside it. In AWS and GCP each secret is a top-level resource and the value is a separate version.

Encryption keys

Not 1:1Capability: key-management

In GCP key rings and crypto keys can't be deleted: a terraform destroy removes them from state and destroys their versions, but the name stays taken.

↗ registry.terraform.io

Access to a specific secret

Not 1:1Capability: secrets-store

In Azure data-plane access to the vault is granted with a role assignment (for example Key Vault Secrets User), recommended at vault scope; assigning it on an individual secret is the exception. In AWS you can combine a resource policy on the secret with an identity policy. In GCP the binding (Secret Manager Secret Accessor) can be granted on the secret.

↗ learn.microsoft.com↗ aws.amazon.com↗ cloud.google.com

Automatic secret rotation

No equivalentCapability: secrets-store

Only AWS has a resource that schedules rotation (with a Lambda function for most secrets). In GCP the secret's rotation block only publishes notifications to Pub/Sub and a subscriber has to create the new version. Azure Key Vault has no rotation resource for secrets: it publishes a near-expiry event to Event Grid and a function does the rotation.

↗ aws.amazon.com↗ cloud.google.com↗ learn.microsoft.com

Auditing secret access

Not 1:1Capability: secrets-store

In Azure the vault's resource logs (AuditEvent category) aren't collected until you create a diagnostic setting. In GCP Data Access audit logs are off by default and are turned on with the project's audit config. In AWS CloudTrail records Secrets Manager calls; a trail (aws_cloudtrail) keeps events beyond the 90-day event history.

↗ learn.microsoft.com↗ cloud.google.com↗ aws.amazon.com

Message queue

Not 1:1Capability: message-queue

Service Bus has a namespace (tier, network, authentication) with queues inside. SQS is one resource per queue. Pub/Sub separates topic and subscription, and messages are retained per subscription.

Functions

Not 1:1Capability: event-driven-compute

An Azure Function App needs its own plan and storage account; Lambda and Cloud Functions are a single resource.

Serverless containers

Not 1:1Capability: container-platform

Container Apps separates environment (network, logs) and app. ECS separates cluster, task definition and service. Cloud Run is a single resource per service.

Managed Kubernetes

Not 1:1Capability: managed-kubernetes

AKS requires a default node pool as a block inside the cluster. For GKE the provider docs recommend removing the default pool (remove_default_node_pool) and managing pools as separate resources. In EKS node groups are always separate resources.

↗ registry.terraform.io

Linux virtual machine

Not 1:1

In Azure the NIC is a separate resource the VM references; in AWS and GCP the primary interface is declared inside the instance.

Centralized logs

Not 1:1Capability: centralized-logging

In Azure resource logs don't reach the workspace until you create a diagnostic setting per resource. In GCP logs already land in the project; sinks route them to another bucket or destination.

↗ learn.microsoft.com↗ cloud.google.com

CDN distribution in front of an origin

Not 1:1Capability: cdn-edge

In CloudFront a single distribution declares origins, cache behaviors and security. Front Door splits that into profile, origin group, origin and route. GCP has no separate CDN resource: Cloud CDN is enabled on a backend bucket behind an external Application Load Balancer (URL map, HTTPS proxy and forwarding rule), and if it isn't enabled at that step the load balancer serves straight from Cloud Storage with no cache.

↗ learn.microsoft.com↗ aws.amazon.com↗ cloud.google.com

Letting only the CDN read the origin

Not 1:1Capability: cdn-edge

Three different mechanisms. Front Door Premium creates a private endpoint to the storage (the origin's private_link block) and the connection must be approved on the origin side before traffic flows. CloudFront signs every request to S3 with an OAC and the bucket needs a policy that allows the cloudfront.amazonaws.com principal with a condition on the distribution. GCP has no OAC-like resource: you grant read on the bucket to the Cloud CDN service account, which only exists once the first signed URL key is added to the backend bucket.

↗ learn.microsoft.com↗ aws.amazon.com↗ cloud.google.com

WAF at the CDN edge

Not 1:1Capability: cdn-edge

In Front Door the WAF policy is a resource and is tied to the endpoint or domain through a separate security policy; managed rules are Premium only. In CloudFront you create an AWS WAF web ACL and associate it with the distribution. In GCP only Cloud Armor edge security policies (type CLOUD_ARMOR_EDGE) can be applied to backend buckets, and they attach to the backend service.

↗ learn.microsoft.com↗ aws.amazon.com↗ cloud.google.com

Time-bound exception to a guardrail

No equivalentCapability: governance-guardrails

Azure Policy has its own exemption object, with a category (waiver or mitigated), an optional expiry (expiresOn; when it passes the object isn't deleted, it just stops being honored) and metadata on who requested and approved it. GCP has no exception object: you set an org policy on the child resource, which replaces the inherited one. AWS has no equivalent resource: an SCP Deny applies to everything under the level where it is attached.

↗ learn.microsoft.com↗ cloud.google.com↗ aws.amazon.com

Sending audit logs to a central destination

Not 1:1Capability: centralized-logging

In AWS an organization trail (is_organization_trail, created from the management account) logs the events of all accounts into a single S3 bucket. In GCP an aggregated sink on the organization or a folder (include_children) routes the logs of everything under it, and its writer identity needs permissions on the destination. In Azure the activity log is per subscription and leaves through a per-subscription diagnostic setting; a management group one doesn't cover every subscription-level event.

↗ aws.amazon.com↗ cloud.google.com↗ learn.microsoft.com

Logging data reads and writes

Not 1:1Capability: centralized-logging

Data-plane events aren't recorded by default in any cloud. In GCP Data Access audit logs are off (except some BigQuery services) and are enabled per service and type (ADMIN_READ, DATA_READ, DATA_WRITE) at organization, folder or project level; Admin Activity logs can't be turned off. In Azure resource logs are enabled through the categories of a per-resource diagnostic setting. In CloudTrail they are the trail's data events, chosen per resource.

↗ cloud.google.com↗ learn.microsoft.com↗ aws.amazon.com