From 08fe5ac9f071125cad379a034fdd7e0f2a8d16f3 Mon Sep 17 00:00:00 2001 From: Tomer Heber Date: Wed, 4 Dec 2024 14:18:18 -0600 Subject: [PATCH] Feat: azapi - not all resources support tags (#210) * Feat: azapi - not all resources support tags * fix test * fix tests * fixed some issues based on PR comments --- .gitignore | 2 + azapi/README.md | 11 + azapi/generate.py | 42 ++ azapi/requirements.txt | 4 + .../providers/azure_resource_tag_support.csv | 620 ++++++++++++++++++ internal/providers/providers.go | 89 ++- internal/tfschema/tfschema.go | 2 +- test/tests/azapi/expected/main.terratag.tf | 43 +- test/tests/azapi/expected/main.tf.bak | 44 +- test/tests/azapi/input/main.tf | 44 +- 10 files changed, 893 insertions(+), 8 deletions(-) create mode 100644 azapi/README.md create mode 100644 azapi/generate.py create mode 100644 azapi/requirements.txt create mode 100644 internal/providers/azure_resource_tag_support.csv diff --git a/.gitignore b/.gitignore index f21a7a44..0bbb966e 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,5 @@ hcl tf dist/ + +venv diff --git a/azapi/README.md b/azapi/README.md new file mode 100644 index 00000000..b2a98625 --- /dev/null +++ b/azapi/README.md @@ -0,0 +1,11 @@ +# azapi + +Utility for parsing Microsoft's azapi resource-tag tables, to locate all resources that can be tagged. +For more information check: https://github.com/env0/terratag/issues/209 + +```bash +python3 -m venv venv +source venv/bin/activate +python install -r ./requirements.txt +python generate.py +``` diff --git a/azapi/generate.py b/azapi/generate.py new file mode 100644 index 00000000..e4197c72 --- /dev/null +++ b/azapi/generate.py @@ -0,0 +1,42 @@ +from io import StringIO +from bs4 import BeautifulSoup +import pandas as pd +import re +import requests + +url = "https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/tag-support" +response = requests.get(url) +html = response.content + +soup = BeautifulSoup(html, "html.parser") + +tables = soup.find_all("table") + +dfs = [] + +for table in tables: + parent_div = table.find_parent("div", class_="mx-tableFixed") + + # Find the h2 within the parent div + title_element = parent_div.find_previous_sibling("h2") + title = title_element.text.strip().lower().replace(" ", "") + + df = pd.read_html(StringIO(str(table)))[0] + + df["Resource type"] = df["Resource type"].apply( + lambda x: ( + f"{title}/{x.lower().replace(' ', '')}" + if title + else x.lower().replace(" ", "") + ) + ) + + dfs.append(df) + +df = pd.concat(dfs) + +df = df[df["Supports tags"] == "Yes"] + +df = df[["Resource type"]] + +df.to_csv("azure_resource_tag_support.csv", index=False) diff --git a/azapi/requirements.txt b/azapi/requirements.txt new file mode 100644 index 00000000..64bc81a3 --- /dev/null +++ b/azapi/requirements.txt @@ -0,0 +1,4 @@ +beautifulsoup4==4.12.3 +pandas==2.2.3 +requests==2.32.3 +lxml==5.3.0 diff --git a/internal/providers/azure_resource_tag_support.csv b/internal/providers/azure_resource_tag_support.csv new file mode 100644 index 00000000..8c8c553f --- /dev/null +++ b/internal/providers/azure_resource_tag_support.csv @@ -0,0 +1,620 @@ +Resource type +microsoft.aad/domainservices +microsoft.aadiam/azureadmetrics +microsoft.aadiam/privatelinkforazuread +microsoft.aadiam/tenants +microsoft.agfoodplatform/farmbeats +microsoft.alertsmanagement/actionrules +microsoft.alertsmanagement/smartdetectoralertrules +microsoft.analysisservices/servers +microsoft.anybuild/clusters +microsoft.apimanagement/service +microsoft.app/connectedenvironments +microsoft.app/connectedenvironments/certificates +microsoft.app/containerapps +microsoft.app/managedenvironments +microsoft.app/managedenvironments/certificates +microsoft.appassessment/migrateprojects +microsoft.appconfiguration/configurationstores +microsoft.appplatform/spring +microsoft.attestation/attestationproviders +microsoft.authorization/resourcemanagementprivatelinks +microsoft.automanage/accounts +microsoft.automanage/configurationprofilepreferences +microsoft.automanage/configurationprofiles +microsoft.automanage/configurationprofiles/versions +microsoft.automanage/patchjobconfigurations +microsoft.automanage/patchschedules +microsoft.automanage/patchschedules/associations +microsoft.automanage/patchtiers +microsoft.automation/automationaccounts +microsoft.automation/automationaccounts/configurations +microsoft.automation/automationaccounts/runbooks +microsoft.automation/automationaccounts/runtimes +microsoft.autonomousdevelopmentplatform/accounts +microsoft.autonomousdevelopmentplatform/workspaces +microsoft.autonomoussystems/workspaces +microsoft.avs/privateclouds +microsoft.azureactivedirectory/b2cdirectories +microsoft.azureactivedirectory/ciamdirectories +microsoft.azureactivedirectory/guestusages +microsoft.azurearcdata/datacontrollers +microsoft.azurearcdata/postgresinstances +microsoft.azurearcdata/sqlmanagedinstances +microsoft.azurearcdata/sqlserverinstances +microsoft.azurearcdata/sqlserverinstances/databases +microsoft.azurearcdata/sqlserverinstances/availabilitygroups +microsoft.azurecis/autopilotenvironments +microsoft.azurecis/dstsserviceaccounts +microsoft.azurecis/dstsserviceclientidentities +microsoft.azurescan/scanningaccounts +microsoft.azuresphere/catalogs +microsoft.azurestack/linkedsubscriptions +microsoft.azurestack/registrations +microsoft.azurestackhci/clusters +microsoft.azurestackhci/galleryimages +microsoft.azurestackhci/marketplacegalleryimages +microsoft.azurestackhci/networkinterfaces +microsoft.azurestackhci/storagecontainers +microsoft.azurestackhci/virtualharddisks +microsoft.azurestackhci/virtualmachines +microsoft.azurestackhci/virtualmachines/extensions +microsoft.azurestackhci/virtualnetworks +microsoft.backupsolutions/vmwareapplications +microsoft.baremetalinfrastructure/baremetalinstances +microsoft.batch/batchaccounts +microsoft.billing/billingaccounts/billingprofiles +microsoft.billing/billingaccounts/billingprofiles/invoicesections +microsoft.bing/accounts +microsoft.blockchaintokens/tokenservices +microsoft.botservice/botservices +microsoft.cache/redis +microsoft.cache/redisenterprise +microsoft.cascade/sites +microsoft.cdn/cdnwebapplicationfirewallpolicies +microsoft.cdn/profiles +microsoft.cdn/profiles/afdendpoints +microsoft.cdn/profiles/endpoints +microsoft.certificateregistration/certificateorders +microsoft.chaos/experiments +microsoft.codesigning/codesigningaccounts +microsoft.codespaces/plans +microsoft.cognitiveservices/accounts +microsoft.communication/communicationservices +microsoft.communication/emailservices +microsoft.communication/emailservices/domains +microsoft.compute/availabilitysets +microsoft.compute/cloudservices +microsoft.compute/diskaccesses +microsoft.compute/diskencryptionsets +microsoft.compute/disks +microsoft.compute/galleries +microsoft.compute/galleries/applications +microsoft.compute/galleries/applications/versions +microsoft.compute/galleries/images +microsoft.compute/galleries/images/versions +microsoft.compute/galleries/serviceartifacts +microsoft.compute/hostgroups +microsoft.compute/hostgroups/hosts +microsoft.compute/images +microsoft.compute/proximityplacementgroups +microsoft.compute/restorepointcollections +microsoft.compute/sharedvmextensions +microsoft.compute/sharedvmextensions/versions +microsoft.compute/sharedvmimages +microsoft.compute/sharedvmimages/versions +microsoft.compute/snapshots +microsoft.compute/sshpublickeys +microsoft.compute/virtualmachines +microsoft.compute/virtualmachines/applications +microsoft.compute/virtualmachines/extensions +microsoft.compute/virtualmachines/runcommands +microsoft.compute/virtualmachinescalesets +microsoft.confidentialledger/ledgers +microsoft.confidentialledger/managedccf +microsoft.confluent/organizations +microsoft.connectedcache/cachenodes +microsoft.connectedcache/enterprisecustomers +microsoft.connectedcache/ispcustomers +microsoft.connectedcache/ispcustomers/ispcachenodes +microsoft.connectedopenstack/flavors +microsoft.connectedopenstack/heatstacks +microsoft.connectedopenstack/heatstacktemplates +microsoft.connectedopenstack/images +microsoft.connectedopenstack/keypairs +microsoft.connectedopenstack/networkports +microsoft.connectedopenstack/networks +microsoft.connectedopenstack/openstackidentities +microsoft.connectedopenstack/securitygrouprules +microsoft.connectedopenstack/securitygroups +microsoft.connectedopenstack/subnets +microsoft.connectedopenstack/virtualmachines +microsoft.connectedopenstack/volumes +microsoft.connectedopenstack/volumesnapshots +microsoft.connectedopenstack/volumetypes +microsoft.connectedvehicle/platformaccounts +microsoft.connectedvmwarevsphere/clusters +microsoft.connectedvmwarevsphere/datastores +microsoft.connectedvmwarevsphere/hosts +microsoft.connectedvmwarevsphere/resourcepools +microsoft.connectedvmwarevsphere/vcenters +microsoft.connectedvmwarevsphere/virtualmachines +microsoft.connectedvmwarevsphere/virtualmachines/extensions +microsoft.connectedvmwarevsphere/virtualmachinetemplates +microsoft.connectedvmwarevsphere/virtualnetworks +microsoft.containerinstance/containergroupprofiles +microsoft.containerinstance/containergroups +microsoft.containerinstance/containerscalesets +microsoft.containerregistry/registries +microsoft.containerregistry/registries/agentpools +microsoft.containerregistry/registries/buildtasks +microsoft.containerregistry/registries/replications +microsoft.containerregistry/registries/tasks +microsoft.containerregistry/registries/webhooks +microsoft.containerservice/containerservices +microsoft.containerservice/fleets +microsoft.containerservice/managedclusters +microsoft.containerservice/managedclustersnapshots +microsoft.containerservice/snapshots +microsoft.costmanagement/connectors +microsoft.customproviders/resourceproviders +microsoft.d365customerinsights/instances +microsoft.dashboard/grafana +microsoft.databox/jobs +microsoft.databoxedge/databoxedgedevices +microsoft.databricks/accessconnectors +microsoft.databricks/workspaces +microsoft.datacatalog/catalogs +microsoft.datacatalog/datacatalogs +microsoft.datacollaboration/workspaces +microsoft.datadog/monitors +microsoft.datafactory/datafactories +microsoft.datafactory/factories +microsoft.datalakeanalytics/accounts +microsoft.datalakestore/accounts +microsoft.datamigration/services +microsoft.datamigration/services/projects +microsoft.datamigration/slots +microsoft.datamigration/sqlmigrationservices +microsoft.dataprotection/backupvaults +microsoft.dataprotection/resourceguards +microsoft.datareplication/replicationfabrics +microsoft.datareplication/replicationvaults +microsoft.datashare/accounts +microsoft.dbformariadb/servers +microsoft.dbformysql/flexibleservers +microsoft.dbformysql/servers +microsoft.dbforpostgresql/flexibleservers +microsoft.dbforpostgresql/servergroups +microsoft.dbforpostgresql/servergroupsv2 +microsoft.dbforpostgresql/servers +microsoft.dbforpostgresql/serversv2 +microsoft.delegatednetwork/controller +microsoft.delegatednetwork/delegatedsubnets +microsoft.delegatednetwork/orchestrators +microsoft.deploymentmanager/artifactsources +microsoft.deploymentmanager/rollouts +microsoft.deploymentmanager/servicetopologies +microsoft.deploymentmanager/servicetopologies/services +microsoft.deploymentmanager/servicetopologies/services/serviceunits +microsoft.deploymentmanager/steps +microsoft.desktopvirtualization/applicationgroups +microsoft.desktopvirtualization/hostpools +microsoft.desktopvirtualization/scalingplans +microsoft.desktopvirtualization/workspaces +microsoft.devai/instances +microsoft.devai/instances/experiments +microsoft.devai/instances/sandboxes +microsoft.devai/instances/sandboxes/experiments +microsoft.devcenter/devcenters +microsoft.devcenter/devcenters/devboxdefinitions +microsoft.devcenter/networkconnections +microsoft.devcenter/projects +microsoft.devcenter/projects/pools +microsoft.devhub/workflows +microsoft.devices/iothubs +microsoft.devices/provisioningservices +microsoft.deviceupdate/accounts +microsoft.deviceupdate/accounts/instances +microsoft.devops/pipelines +microsoft.devtestlab/labcenters +microsoft.devtestlab/labs +microsoft.devtestlab/labs/environments +microsoft.devtestlab/labs/servicerunners +microsoft.devtestlab/labs/virtualmachines +microsoft.devtestlab/schedules +microsoft.digitaltwins/digitaltwinsinstances +microsoft.documentdb/cassandraclusters +microsoft.documentdb/mongoclusters +microsoft.documentdb/databaseaccounts +microsoft.domainregistration/domains +microsoft.edgeorder/addresses +microsoft.edgeorder/orderitems +microsoft.elastic/monitors +microsoft.eventgrid/domains +microsoft.eventgrid/namespaces +microsoft.eventgrid/partnerconfigurations +microsoft.eventgrid/partnerdestinations +microsoft.eventgrid/partnernamespaces +microsoft.eventgrid/partnerregistrations +microsoft.eventgrid/partnertopics +microsoft.eventgrid/systemtopics +microsoft.eventgrid/topics +microsoft.eventhub/clusters +microsoft.eventhub/namespaces +microsoft.falcon/namespaces +microsoft.fidalgo/devcenters +microsoft.fidalgo/devcenters/devboxdefinitions +microsoft.fidalgo/machinedefinitions +microsoft.fidalgo/networksettings +microsoft.fidalgo/projects +microsoft.fidalgo/projects/environments +microsoft.fidalgo/projects/pools +microsoft.fluidrelay/fluidrelayservers +microsoft.graph/azureadapplication +microsoft.graph/azureadapplicationprototype +microsoft.hanaonazure/hanainstances +microsoft.hanaonazure/sapmonitors +microsoft.hardwaresecuritymodules/dedicatedhsms +microsoft.hdinsight/clusterpools +microsoft.hdinsight/clusterpools/clusters +microsoft.hdinsight/clusterpools/clusters/sessionclusters +microsoft.hdinsight/clusters +microsoft.healthbot/healthbots +microsoft.healthcareapis/services +microsoft.healthcareapis/workspaces +microsoft.healthcareapis/workspaces/analyticsconnectors +microsoft.healthcareapis/workspaces/dicomservices +microsoft.healthcareapis/workspaces/fhirservices +microsoft.healthcareapis/workspaces/iotconnectors +microsoft.hpcworkbench/instances +microsoft.hpcworkbench/instances/chambers +microsoft.hpcworkbench/instances/chambers/accessprofiles +microsoft.hpcworkbench/instances/chambers/workloads +microsoft.hpcworkbench/instances/consortiums +microsoft.hybridcompute/machines +microsoft.hybridcompute/machines/extensions +microsoft.hybridcompute/privatelinkscopes +microsoft.hybridcontainerservice/provisionedclusters +microsoft.hybridcontainerservice/provisionedclusters/agentpools +microsoft.hybridcontainerservice/storagespaces +microsoft.hybridcontainerservice/virtualnetworks +microsoft.hybriddata/datamanagers +microsoft.hybridnetwork/configurationgroupvalues +microsoft.hybridnetwork/devices +microsoft.hybridnetwork/networkfunctions +microsoft.hybridnetwork/publishers +microsoft.hybridnetwork/publishers/artifactstores +microsoft.hybridnetwork/publishers/artifactstores/artifactmanifests +microsoft.hybridnetwork/publishers/configurationgroupschemas +microsoft.hybridnetwork/publishers/networkfunctiondefinitiongroups +microsoft.hybridnetwork/publishers/networkfunctiondefinitiongroups/networkfunctiondefinitionversions +microsoft.hybridnetwork/publishers/networkfunctiondefinitiongroups/previewsubscriptions +microsoft.hybridnetwork/publishers/networkservicedesigngroups +microsoft.hybridnetwork/publishers/networkservicedesigngroups/networkservicedesignversions +microsoft.hybridnetwork/sitenetworkservices +microsoft.hybridnetwork/sites +microsoft.importexport/jobs +microsoft.insights/actiongroups +microsoft.insights/activitylogalerts +microsoft.insights/alertrules +microsoft.insights/autoscalesettings +microsoft.insights/components +microsoft.insights/datacollectionendpoints +microsoft.insights/datacollectionrules +microsoft.insights/guestdiagnosticsettings +microsoft.insights/metricalerts +microsoft.insights/notificationgroups +microsoft.insights/privatelinkscopes +microsoft.insights/scheduledqueryrules +microsoft.insights/webtests +microsoft.insights/workbooks +microsoft.insights/workbooktemplates +microsoft.intelligentitdigitaltwin/digitaltwins +microsoft.intelligentitdigitaltwin/digitaltwins/assets +microsoft.intelligentitdigitaltwin/digitaltwins/executionplans +microsoft.intelligentitdigitaltwin/digitaltwins/testplans +microsoft.intelligentitdigitaltwin/digitaltwins/tests +microsoft.iotcentral/iotapps +microsoft.keyvault/hsmpools +microsoft.keyvault/managedhsms +microsoft.keyvault/vaults +microsoft.keyvault/vaults/secrets +microsoft.kubernetes/connectedclusters +microsoft.kubernetesconfiguration/privatelinkscopes +microsoft.kusto/clusters +microsoft.labservices/labaccounts +microsoft.labservices/labplans +microsoft.labservices/labs +microsoft.loadtestservice/loadtests +microsoft.logic/hostingenvironments +microsoft.logic/integrationaccounts +microsoft.logic/integrationserviceenvironments +microsoft.logic/integrationserviceenvironments/managedapis +microsoft.logic/isolatedenvironments +microsoft.logic/workflows +microsoft.logz/monitors +microsoft.logz/monitors/accounts +microsoft.logz/monitors/metricssource +microsoft.machinelearning/commitmentplans +microsoft.machinelearning/webservices +microsoft.machinelearning/workspaces +microsoft.machinelearningservices/aisysteminventories +microsoft.machinelearningservices/registries +microsoft.machinelearningservices/virtualclusters +microsoft.machinelearningservices/workspaces +microsoft.machinelearningservices/workspaces/batchendpoints +microsoft.machinelearningservices/workspaces/batchendpoints/deployments +microsoft.machinelearningservices/workspaces/onlineendpoints +microsoft.machinelearningservices/workspaces/onlineendpoints/deployments +microsoft.maintenance/maintenanceconfigurations +microsoft.managedidentity/userassignedidentities +microsoft.maps/accounts +microsoft.maps/accounts/creators +microsoft.media/mediaservices +microsoft.media/mediaservices/liveevents +microsoft.media/mediaservices/streamingendpoints +microsoft.media/videoanalyzers +microsoft.migrate/assessmentprojects +microsoft.migrate/migrateprojects +microsoft.migrate/modernizeprojects +microsoft.migrate/movecollections +microsoft.migrate/projects +microsoft.mixedreality/objectanchorsaccounts +microsoft.mixedreality/objectunderstandingaccounts +microsoft.mixedreality/remoterenderingaccounts +microsoft.mixedreality/spatialanchorsaccounts +microsoft.mobilenetwork/mobilenetworks +microsoft.mobilenetwork/mobilenetworks/datanetworks +microsoft.mobilenetwork/mobilenetworks/services +microsoft.mobilenetwork/mobilenetworks/simpolicies +microsoft.mobilenetwork/mobilenetworks/sites +microsoft.mobilenetwork/mobilenetworks/slices +microsoft.mobilenetwork/packetcorecontrolplanes +microsoft.mobilenetwork/packetcorecontrolplanes/packetcoredataplanes +microsoft.mobilenetwork/packetcorecontrolplanes/packetcoredataplanes/attacheddatanetworks +microsoft.mobilenetwork/simgroups +microsoft.mobilenetwork/sims +microsoft.monitor/accounts +microsoft.netapp/netappaccounts +microsoft.netapp/netappaccounts/backuppolicies +microsoft.netapp/netappaccounts/capacitypools +microsoft.netapp/netappaccounts/capacitypools/volumes +microsoft.netapp/netappaccounts/snapshotpolicies +microsoft.network/applicationgateways +microsoft.network/applicationgatewaywebapplicationfirewallpolicies +microsoft.network/applicationsecuritygroups +microsoft.network/azurefirewalls +microsoft.network/bastionhosts +microsoft.network/connections +microsoft.network/customipprefixes +microsoft.network/ddoscustompolicies +microsoft.network/ddosprotectionplans +microsoft.network/dnsforwardingrulesets +microsoft.network/dnsresolvers +microsoft.network/dnsresolvers/inboundendpoints +microsoft.network/dnsresolvers/outboundendpoints +microsoft.network/dnszones +microsoft.network/dscpconfigurations +microsoft.network/expressroutecircuits +microsoft.network/expressroutecrossconnections +microsoft.network/expressroutegateways +microsoft.network/expressrouteports +microsoft.network/ipgroups +microsoft.network/loadbalancers +microsoft.network/localnetworkgateways +microsoft.network/natgateways +microsoft.network/networkexperimentprofiles +microsoft.network/networkintentpolicies +microsoft.network/networkinterfaces +microsoft.network/networkmanagers +microsoft.network/networkprofiles +microsoft.network/networksecuritygroups +microsoft.network/networksecurityperimeters +microsoft.network/networkvirtualappliances +microsoft.network/networkwatchers +microsoft.network/networkwatchers/connectionmonitors +microsoft.network/networkwatchers/flowlogs +microsoft.network/networkwatchers/lenses +microsoft.network/networkwatchers/pingmeshes +microsoft.network/p2svpngateways +microsoft.network/privatednszones +microsoft.network/privatednszones/virtualnetworklinks +microsoft.network/privateendpointredirectmaps +microsoft.network/privateendpoints +microsoft.network/privatelinkservices +microsoft.network/publicipaddresses +microsoft.network/publicipprefixes +microsoft.network/routefilters +microsoft.network/routetables +microsoft.network/securitypartnerproviders +microsoft.network/serviceendpointpolicies +microsoft.network/virtualhubs +microsoft.network/virtualnetworkgateways +microsoft.network/virtualnetworks +microsoft.network/virtualnetworktaps +microsoft.network/virtualrouters +microsoft.network/virtualwans +microsoft.network/vpngateways +microsoft.network/vpnserverconfigurations +microsoft.network/vpnsites +microsoft.networkcloud/baremetalmachines +microsoft.networkcloud/cloudservicesnetworks +microsoft.networkcloud/clustermanagers +microsoft.networkcloud/clusters +microsoft.networkcloud/defaultcninetworks +microsoft.networkcloud/disks +microsoft.networkcloud/hybridaksclusters +microsoft.networkcloud/hybridaksmanagementdomains +microsoft.networkcloud/hybridaksvirtualmachines +microsoft.networkcloud/l2networks +microsoft.networkcloud/l3networks +microsoft.networkcloud/rackmanifests +microsoft.networkcloud/racks +microsoft.networkcloud/storageappliances +microsoft.networkcloud/trunkednetworks +microsoft.networkcloud/virtualmachines +microsoft.networkcloud/workloadnetworks +microsoft.networkfunction/azuretrafficcollectors +microsoft.networkfunction/azuretrafficcollectors/collectorpolicies +microsoft.networkfunction/meshvpns +microsoft.networkfunction/meshvpns/connectionpolicies +microsoft.notificationhubs/namespaces +microsoft.notificationhubs/namespaces/notificationhubs +microsoft.objectstore/osnamespaces +microsoft.offazure/hypervsites +microsoft.offazure/importsites +microsoft.offazure/mastersites +microsoft.offazure/serversites +microsoft.offazure/vmwaresites +microsoft.openenergyplatform/energyservices +microsoft.openlogisticsplatform/applicationmanagers +microsoft.openlogisticsplatform/applicationworkspaces +microsoft.openlogisticsplatform/workspaces +microsoft.operationalinsights/clusters +microsoft.operationalinsights/querypacks +microsoft.operationalinsights/workspaces +microsoft.orbital/contactprofiles +microsoft.orbital/edgesites +microsoft.orbital/groundstations +microsoft.orbital/l2connections +microsoft.orbital/l3connections +microsoft.orbital/orbitalgateways +microsoft.orbital/spacecrafts +microsoft.peering/peerings +microsoft.peering/peeringservices +microsoft.pki/pkis +microsoft.pki/pkis/enrollmentpolicies +microsoft.playfab/playeraccountpools +microsoft.playfab/titles +microsoft.portal/dashboards +microsoft.powerbi/privatelinkservicesforpowerbi +microsoft.powerbi/tenants +microsoft.powerbi/workspacecollections +microsoft.powerbidedicated/autoscalevcores +microsoft.powerbidedicated/capacities +microsoft.powerbidedicated/servers +microsoft.powerplatform/accounts +microsoft.powerplatform/enterprisepolicies +microsoft.purview/accounts +microsoft.quantum/workspaces +microsoft.recommendationsservice/accounts +microsoft.recommendationsservice/accounts/modeling +microsoft.recommendationsservice/accounts/serviceendpoints +microsoft.recoveryservices/vaults +microsoft.recoveryservices/vaults/backuppolicies +microsoft.redhatopenshift/openshiftclusters +microsoft.relay/namespaces +microsoft.resourceconnector/appliances +microsoft.resourcegraph/queries +microsoft.resources/deployments +microsoft.resources/deploymentscripts +microsoft.resources/resourcegroups +microsoft.resources/subscriptions +microsoft.resources/templatespecs +microsoft.resources/templatespecs/versions +microsoft.saas/applications +microsoft.saas/resources +microsoft.scom/managedinstances +microsoft.scvmm/availabilitysets +microsoft.scvmm/clouds +microsoft.scvmm/virtualmachines +microsoft.scvmm/virtualmachinetemplates +microsoft.scvmm/virtualnetworks +microsoft.scvmm/vmmservers +microsoft.search/searchservices +microsoft.security/assignments +microsoft.security/automations +microsoft.security/customassessmentautomations +microsoft.security/customentitystoreassignments +microsoft.security/datascanners +microsoft.security/iotsecuritysolutions +microsoft.security/securityconnectors +microsoft.security/standards +microsoft.securitydetonation/chambers +microsoft.securitydevops/azuredevopsconnectors +microsoft.securitydevops/githubconnectors +microsoft.servicebus/namespaces +microsoft.servicefabric/clusters +microsoft.servicefabric/edgeclusters +microsoft.servicefabric/managedclusters +microsoft.serviceshub/connectors +microsoft.signalrservice/signalr +microsoft.signalrservice/webpubsub +microsoft.singularity/accounts +microsoft.solutions/applicationdefinitions +microsoft.solutions/applications +microsoft.solutions/jitrequests +microsoft.sql/instancepools +microsoft.sql/managedinstances +microsoft.sql/managedinstances/databases +microsoft.sql/servers +microsoft.sql/servers/databases +microsoft.sql/servers/elasticpools +microsoft.sql/servers/jobaccounts +microsoft.sql/servers/jobagents +microsoft.sql/virtualclusters +microsoft.sqlvirtualmachine/sqlvirtualmachinegroups +microsoft.sqlvirtualmachine/sqlvirtualmachines +microsoft.storage/datamovers +microsoft.storage/storageaccounts +microsoft.storage/storagetasks +microsoft.storagecache/amlfilesystems +microsoft.storagecache/caches +microsoft.storagemover/storagemovers +microsoft.storagepool/diskpools +microsoft.storagesync/storagesyncservices +microsoft.storsimple/managers +microsoft.streamanalytics/clusters +microsoft.streamanalytics/streamingjobs +microsoft.synapse/privatelinkhubs +microsoft.synapse/workspaces +microsoft.synapse/workspaces/bigdatapools +microsoft.synapse/workspaces/kustopools +microsoft.synapse/workspaces/sqldatabases +microsoft.synapse/workspaces/sqlpools +microsoft.testbase/testbaseaccounts +microsoft.testbase/testbaseaccounts/packages +microsoft.timeseriesinsights/environments +microsoft.timeseriesinsights/environments/eventsources +microsoft.timeseriesinsights/environments/referencedatasets +microsoft.usagebilling/accounts +microsoft.videoindexer/accounts +microsoft.virtualmachineimages/imagetemplates +microsoft.visualstudio/account +microsoft.visualstudio/account/extension +microsoft.visualstudio/account/project +microsoft.vmware/arczones +microsoft.vmware/resourcepools +microsoft.vmware/vcenters +microsoft.vmware/virtualmachines +microsoft.vmware/virtualmachinetemplates +microsoft.vmware/virtualnetworks +microsoft.vmwarecloudsimple/dedicatedcloudnodes +microsoft.vmwarecloudsimple/dedicatedcloudservices +microsoft.vmwarecloudsimple/virtualmachines +microsoft.vsonline/accounts +microsoft.vsonline/plans +microsoft.web/certificates +microsoft.web/connectiongateways +microsoft.web/connections +microsoft.web/containerapps +microsoft.web/customapis +microsoft.web/hostingenvironments +microsoft.web/kubeenvironments +microsoft.web/serverfarms +microsoft.web/sites +microsoft.web/sites/premieraddons +microsoft.web/sites/slots +microsoft.web/staticsites +microsoft.web/workerapps +microsoft.windowsesu/multipleactivationkeys +microsoft.windowsiot/deviceservices +microsoft.workloadbuilder/migrationagents +microsoft.workloadbuilder/workloads +microsoft.workloads/monitors +microsoft.workloads/phpworkloads +microsoft.workloads/sapvirtualinstances +microsoft.workloads/sapvirtualinstances/applicationinstances +microsoft.workloads/sapvirtualinstances/centralinstances +microsoft.workloads/sapvirtualinstances/databaseinstances \ No newline at end of file diff --git a/internal/providers/providers.go b/internal/providers/providers.go index 40b938a7..d6642053 100644 --- a/internal/providers/providers.go +++ b/internal/providers/providers.go @@ -1,7 +1,14 @@ package providers import ( + "bytes" + _ "embed" + "encoding/csv" "strings" + "sync" + + "github.com/hashicorp/hcl/v2/hclsyntax" + "github.com/hashicorp/hcl/v2/hclwrite" ) const AWS = "aws" @@ -18,6 +25,32 @@ var prefixes = map[string]Provider{ "azapi_": AZURE, } +//go:embed azure_resource_tag_support.csv +var azureTagSupport []byte + +var ( + azureTaggableResources map[string]bool + once sync.Once +) + +func getAzureTaggableResources() map[string]bool { + once.Do(func() { + reader := csv.NewReader(bytes.NewReader(azureTagSupport)) + records, err := reader.ReadAll() + + if err != nil { + panic(err) // Or handle the error appropriately + } + + azureTaggableResources = make(map[string]bool) + for _, record := range records { + azureTaggableResources[record[0]] = true + } + }) + + return azureTaggableResources +} + func getProviderByResource(resourceType string) Provider { for prefix, provider := range prefixes { if strings.HasPrefix(resourceType, prefix) { @@ -51,14 +84,66 @@ func GetTagIdByResource(resourceType string) string { return "" } -func IsSupportedResource(resourceType string) bool { +func isSimpleStringLiteral(tokens hclwrite.Tokens) (string, bool) { + if len(tokens) == 3 && + tokens[0].Type == hclsyntax.TokenOQuote && + tokens[1].Type == hclsyntax.TokenQuotedLit && + tokens[2].Type == hclsyntax.TokenCQuote { + return string(tokens[1].Bytes), true // Quoted + } + + return "", false +} + +// For more details check: https://github.com/env0/terratag/issues/209 +func isAzureTypeTaggable(resource hclwrite.Block) bool { + typeAttr := resource.Body().GetAttribute("type") + + if typeAttr == nil { + return false + } + + typeTokens := typeAttr.Expr().BuildTokens(nil) + + typeValue, ok := isSimpleStringLiteral(typeTokens) + + if !ok || typeValue == "" { + return false + } + + // split the type value to get the resource type, get everything before "@" lower cased. + parts := strings.Split(typeValue, "@") + if len(parts) != 2 { + return false + } + + resourceType := strings.ToLower(parts[0]) + + // check if the resource type is taggable based on the on list of supported azure tags. + azureTaggableResources := getAzureTaggableResources() + if _, ok := azureTaggableResources[resourceType]; !ok { + return false + } + + return true +} + +func IsSupportedResource(resourceType string, resource hclwrite.Block) bool { for _, resourceToSkip := range resourcesToSkip { if resourceType == resourceToSkip { return false } } - return isSupportedProvider(getProviderByResource(resourceType)) + if !isSupportedProvider(getProviderByResource(resourceType)) { + return false + } + + if strings.HasPrefix(resourceType, "azapi_") && !isAzureTypeTaggable(resource) { + return false + } + + return true } func isSupportedProvider(provider Provider) bool { diff --git a/internal/tfschema/tfschema.go b/internal/tfschema/tfschema.go index 3c64c7da..0d7286c0 100644 --- a/internal/tfschema/tfschema.go +++ b/internal/tfschema/tfschema.go @@ -56,7 +56,7 @@ func IsTaggable(dir string, iacType common.IACType, defaultToTerraform bool, res resourceType := terraform.GetResourceType(resource) - if providers.IsSupportedResource(resourceType) { + if providers.IsSupportedResource(resourceType, resource) { resourceSchema, err := getResourceSchema(resourceType, resource, dir, iacType, defaultToTerraform) if err != nil { if errors.Is(err, ErrResourceTypeNotFound) { diff --git a/test/tests/azapi/expected/main.terratag.tf b/test/tests/azapi/expected/main.terratag.tf index 06d15858..d579a326 100644 --- a/test/tests/azapi/expected/main.terratag.tf +++ b/test/tests/azapi/expected/main.terratag.tf @@ -195,7 +195,48 @@ resource "azapi_update_resource" "example" { depends_on = [ azurerm_lb_nat_rule.example, ] -} +} + +resource "azapi_resource" "example4" { + type = "Microsoft.App/containerApps/authConfigs@2024-03-01" + name = "current" + parent_id = azurerm_resource_group.example.id + body = { + properties = { + globalValidation = { + redirectToProvider = "azureactivedirectory" + unauthenticatedClientAction = "RedirectToLoginPage" + } + identityProviders = { + azureActiveDirectory = { + enabled = true + isAutoProvisioned = false + registration = { + clientId = "example" + clientSecretSettingName = "microsoft-provider-authentication-secret" + openIdIssuer = "https://sts.windows.net/v2.0" + } + validation = { + allowedAudiences = [ + "example", + ] + defaultAuthorizationPolicy = { + allowedApplications = [ + "example", + ] + } + } + } + } + login = {} + platform = { + enabled = true + runtimeVersion = "~2" + } + } + } +} + locals { terratag_added_main = {"env0_environment_id"="40907eff-cf7c-419a-8694-e1c6bf1d1168","env0_project_id"="43fd4ff1-8d37-4d9d-ac97-295bd850bf94"} } diff --git a/test/tests/azapi/expected/main.tf.bak b/test/tests/azapi/expected/main.tf.bak index ccd3a273..539f3a79 100644 --- a/test/tests/azapi/expected/main.tf.bak +++ b/test/tests/azapi/expected/main.tf.bak @@ -131,7 +131,7 @@ resource "azapi_resource_action" "start" { response_export_values = ["*"] count = var.enabled ? 1 : 0 - } +} resource "azapi_resource_action" "stop" { type = "Microsoft.AppPlatform/Spring@2022-05-01-preview" @@ -189,4 +189,44 @@ resource "azapi_update_resource" "example" { depends_on = [ azurerm_lb_nat_rule.example, ] -} \ No newline at end of file +} + +resource "azapi_resource" "example4" { + type = "Microsoft.App/containerApps/authConfigs@2024-03-01" + name = "current" + parent_id = azurerm_resource_group.example.id + body = { + properties = { + globalValidation = { + redirectToProvider = "azureactivedirectory" + unauthenticatedClientAction = "RedirectToLoginPage" + } + identityProviders = { + azureActiveDirectory = { + enabled = true + isAutoProvisioned = false + registration = { + clientId = "example" + clientSecretSettingName = "microsoft-provider-authentication-secret" + openIdIssuer = "https://sts.windows.net/v2.0" + } + validation = { + allowedAudiences = [ + "example", + ] + defaultAuthorizationPolicy = { + allowedApplications = [ + "example", + ] + } + } + } + } + login = {} + platform = { + enabled = true + runtimeVersion = "~2" + } + } + } +} diff --git a/test/tests/azapi/input/main.tf b/test/tests/azapi/input/main.tf index ccd3a273..539f3a79 100644 --- a/test/tests/azapi/input/main.tf +++ b/test/tests/azapi/input/main.tf @@ -131,7 +131,7 @@ resource "azapi_resource_action" "start" { response_export_values = ["*"] count = var.enabled ? 1 : 0 - } +} resource "azapi_resource_action" "stop" { type = "Microsoft.AppPlatform/Spring@2022-05-01-preview" @@ -189,4 +189,44 @@ resource "azapi_update_resource" "example" { depends_on = [ azurerm_lb_nat_rule.example, ] -} \ No newline at end of file +} + +resource "azapi_resource" "example4" { + type = "Microsoft.App/containerApps/authConfigs@2024-03-01" + name = "current" + parent_id = azurerm_resource_group.example.id + body = { + properties = { + globalValidation = { + redirectToProvider = "azureactivedirectory" + unauthenticatedClientAction = "RedirectToLoginPage" + } + identityProviders = { + azureActiveDirectory = { + enabled = true + isAutoProvisioned = false + registration = { + clientId = "example" + clientSecretSettingName = "microsoft-provider-authentication-secret" + openIdIssuer = "https://sts.windows.net/v2.0" + } + validation = { + allowedAudiences = [ + "example", + ] + defaultAuthorizationPolicy = { + allowedApplications = [ + "example", + ] + } + } + } + } + login = {} + platform = { + enabled = true + runtimeVersion = "~2" + } + } + } +}