Azure / terraform-provider-azapi

Terraform provider for Azure Resource Manager Rest API
https://registry.terraform.io/providers/Azure/azapi/latest
Mozilla Public License 2.0
173 stars 47 forks source link

Support tenant/subscription/extension/management group scope resources #38

Closed ms-henglu closed 2 years ago

ms-henglu commented 2 years ago

Here're the list extracted from bicep-types-az

types.Unknown
Microsoft.Advisor/recommendations/suppressions
Microsoft.Authorization/locks
Microsoft.Authorization/policyAssignments
Microsoft.Authorization/policyExemptions
Microsoft.Authorization/policyPricings
Microsoft.Authorization/policyassignments
Microsoft.Authorization/roleAssignmentApprovals/stages
Microsoft.Authorization/roleAssignmentScheduleRequests
Microsoft.Authorization/roleAssignments
Microsoft.Authorization/roleDefinitions
Microsoft.Authorization/roleEligibilityScheduleRequests
Microsoft.Authorization/roleManagementPolicyAssignments
Microsoft.Blueprint/blueprintAssignments
Microsoft.Blueprint/blueprints
Microsoft.Blueprint/blueprints/versions
Microsoft.Consumption/budgets
Microsoft.CostManagement/budgets
Microsoft.CostManagement/exports
Microsoft.CostManagement/views
Microsoft.CustomProviders/associations
Microsoft.EventGrid/eventSubscriptions
Microsoft.Insights/dataCollectionRuleAssociations
Microsoft.Insights/diagnosticSettings
Microsoft.IoTSecurity/sensors
Microsoft.IoTSecurity/sites
Microsoft.ManagedNetwork/scopeAssignments
Microsoft.ManagedServices/registrationAssignments
Microsoft.ManagedServices/registrationDefinitions
Microsoft.PolicyInsights/attestations
Microsoft.PolicyInsights/remediations
Microsoft.Quota/quotaLimits
Microsoft.Quota/quotas
Microsoft.Resources/deployments
Microsoft.Resources/tags
Microsoft.Security/advancedThreatProtectionSettings
Microsoft.Security/assessments
Microsoft.Security/deviceSecurityGroups
Microsoft.Security/informationProtectionPolicies
Microsoft.Security/sqlVulnerabilityAssessments/baselineRules
Microsoft.ServiceLinker/linkers
Microsoft.SoftwarePlan/hybridUseBenefits
microsoft.insights/diagnosticSettings
microsoft.insights/guestDiagnosticSettingsAssociation

types.Tenant
Microsoft.Billing/billingAccounts/billingProfiles
Microsoft.Billing/billingAccounts/billingProfiles/instructions
Microsoft.Billing/billingAccounts/billingProfiles/invoiceSections
Microsoft.Billing/billingAccounts/billingProfiles/policies
Microsoft.Billing/billingAccounts/billingRoleAssignments
Microsoft.Billing/billingAccounts/customers/policies
Microsoft.Billing/billingAccounts/departments/billingRoleAssignments
Microsoft.Billing/billingAccounts/enrollmentAccounts/billingRoleAssignments
Microsoft.Billing/billingAccounts/invoiceSections
Microsoft.Billing/promotions
Microsoft.Capacity/reservationOrders
Microsoft.CostManagement/cloudConnectors
Microsoft.CostManagement/settings
Microsoft.Intune/locations/androidPolicies
Microsoft.Intune/locations/androidPolicies/apps
Microsoft.Intune/locations/androidPolicies/groups
Microsoft.Intune/locations/iosPolicies
Microsoft.Intune/locations/iosPolicies/apps
Microsoft.Intune/locations/iosPolicies/groups
Microsoft.Management/managementGroups
Microsoft.Management/managementGroups/settings
Microsoft.Management/managementGroups/subscriptions
Microsoft.ManagementPartner/partners
Microsoft.Marketplace/privateStores
Microsoft.Marketplace/privateStores/adminRequestApprovals
Microsoft.Marketplace/privateStores/collections
Microsoft.Marketplace/privateStores/collections/offers
Microsoft.Marketplace/privateStores/offers
Microsoft.Marketplace/privateStores/requestApprovals
Microsoft.Portal/consoles
Microsoft.Portal/locations/consoles
Microsoft.Portal/locations/userSettings
Microsoft.Portal/tenantConfigurations
Microsoft.Portal/userSettings
Microsoft.Subscription/aliases
Microsoft.Subscription/subscriptionDefinitions
Microsoft.Web/publishingUsers
Microsoft.Web/sourcecontrols
microsoft.aadiam/diagnosticSettings

types.ManagementGroup
Microsoft.Authorization/policyDefinitions
Microsoft.Authorization/policySetDefinitions
Microsoft.Authorization/privateLinkAssociations
Microsoft.Blueprint/blueprints/artifacts
Microsoft.CostManagement/externalSubscriptions

types.Subscription
Microsoft.Addons/supportProviders/supportPlanTypes
Microsoft.Advisor/configurations
Microsoft.Authorization/accessReviewScheduleDefinitions
Microsoft.Authorization/accessReviewScheduleDefinitions/instances
Microsoft.Authorization/accessReviewScheduleSettings
Microsoft.Authorization/policyDefinitions
Microsoft.Authorization/policySetDefinitions
Microsoft.Authorization/policydefinitions
Microsoft.Billing/billingAccounts/lineOfCredit
Microsoft.Capacity/resourceProviders/locations/serviceLimits
Microsoft.ChangeAnalysis/profile
Microsoft.Confluent/agreements
Microsoft.CostManagement/reportconfigs
Microsoft.CostManagement/reports
Microsoft.Datadog/agreements
Microsoft.Features/featureProviders/subscriptionFeatureRegistrations
Microsoft.HybridNetwork/locations/vendors/networkFunctions
Microsoft.HybridNetwork/vendors
Microsoft.HybridNetwork/vendors/vendorSkus
Microsoft.HybridNetwork/vendors/vendorSkus/previewSubscriptions
Microsoft.Insights/logprofiles
Microsoft.IoTSecurity/defenderSettings
Microsoft.IoTSecurity/locations/deviceGroups
Microsoft.IoTSecurity/locations/sites
Microsoft.IoTSecurity/locations/sites/sensors
Microsoft.IoTSecurity/onPremiseSensors
Microsoft.Marketplace/privateStores/offers
Microsoft.MarketplaceOrdering/offerTypes/publishers/offers/plans/agreements
Microsoft.Network/trafficManagerUserMetricsKeys
Microsoft.Peering/peerAsns
Microsoft.ProviderHub/providerRegistrations
Microsoft.ProviderHub/providerRegistrations/customRollouts
Microsoft.ProviderHub/providerRegistrations/defaultRollouts
Microsoft.ProviderHub/providerRegistrations/notificationRegistrations
Microsoft.ProviderHub/providerRegistrations/operations
Microsoft.ProviderHub/providerRegistrations/resourcetypeRegistrations
Microsoft.ProviderHub/providerRegistrations/resourcetypeRegistrations/resourcetypeRegistrations/resourcetypeRegistrations/resourcetypeRegistrations/skus
Microsoft.ProviderHub/providerRegistrations/resourcetypeRegistrations/resourcetypeRegistrations/resourcetypeRegistrations/skus
Microsoft.ProviderHub/providerRegistrations/resourcetypeRegistrations/resourcetypeRegistrations/skus
Microsoft.ProviderHub/providerRegistrations/resourcetypeRegistrations/skus
Microsoft.Resources/resourceGroups
Microsoft.Security/alertsSuppressionRules
Microsoft.Security/assessmentMetadata
Microsoft.Security/autoProvisioningSettings
Microsoft.Security/connectors
Microsoft.Security/ingestionSettings
Microsoft.Security/locations/applicationWhitelistings
Microsoft.Security/pricings
Microsoft.Security/securityContacts
Microsoft.Security/settings
Microsoft.Security/workspaceSettings
Microsoft.Support/supportTickets
Microsoft.Support/supportTickets/communications

types.Extension
Microsoft.Automanage/configurationProfileAssignments
Microsoft.CostManagement/costAllocationRules
Microsoft.CostManagement/reports
Microsoft.CostManagement/showbackRules
Microsoft.GuestConfiguration/guestConfigurationAssignments
Microsoft.KubernetesConfiguration/extensions
Microsoft.KubernetesConfiguration/sourceControlConfigurations
Microsoft.Maintenance/applyUpdates
Microsoft.Maintenance/configurationAssignments
Microsoft.OperationsManagement/ManagementAssociations
Microsoft.Security/serverVulnerabilityAssessments
Microsoft.SecurityInsights/alertRules
Microsoft.SecurityInsights/alertRules/actions
Microsoft.SecurityInsights/automationRules
Microsoft.SecurityInsights/bookmarks
Microsoft.SecurityInsights/bookmarks/relations
Microsoft.SecurityInsights/cases
Microsoft.SecurityInsights/cases/comments
Microsoft.SecurityInsights/cases/relations
Microsoft.SecurityInsights/dataConnectors
Microsoft.SecurityInsights/entityQueries
Microsoft.SecurityInsights/incidents
Microsoft.SecurityInsights/incidents/comments
Microsoft.SecurityInsights/incidents/relations
Microsoft.SecurityInsights/metadata
Microsoft.SecurityInsights/onboardingStates
Microsoft.SecurityInsights/settings
Microsoft.SecurityInsights/sourcecontrols
Microsoft.SecurityInsights/threatIntelligence/indicators
Microsoft.SecurityInsights/watchlists
Microsoft.SecurityInsights/watchlists/watchlistItems
Microsoft.SerialConsole/serialPorts
Microsoft.WorkloadMonitor/notificationSettings
ms-henglu commented 2 years ago

There're 2 options:

  1. Introduce scope attribute, defaults to ResourceGroup scope.
  2. Based on bicep-types-az, scope can be inferred from type, but new resource can't be supported without the latest bicep-types-az
grayzu commented 2 years ago

We still need to be able to provide the target of the scope, even if we infer the scope from the type. For example, if the scope is Management group, which management group should it be created in? Possibly use a scope property to reference the ID of the target.

ms-henglu commented 2 years ago

We can reuse the parent_id to get the target scope, for example, the target management group.

Let me add more details.

def:

  1. Root Resource / Top-Level Resource: A resource with only a single level of nested types (i.e. there's just a single type after the RP namespace). Microsoft.Network/networkSecurityGroups is a top-level resource, whereas Microsoft.Network/networkSecurityGroups/securityRules is not.
  2. Child Resource / Nested Resource: A resource with two or more levels of nested types.
  3. Parent Resource: The parent to a child resource, identified by removing a level of nesting from the resource type. Microsoft.Network/networkSecurityGroups is the parent to Microsoft.Network/networkSecuriyGroups/securityRules.

scopes:

  1. Tenant Scope

    1. top level resource: parent_id = / or empty
    2. child resource: parent_id = {its parent resource id}, the parent resource is tenant scope resource, so it will starts with /providers/Microsoft.Somthing
  2. Subscription Scope

    1. top level resource: parent_id = /subscriptions/{subscriptionId}/
    2. child resource: parent_id = {its parent resource id}, the parent resource is a subscription scope resource, so it will starts with /subscriptions/{subscriptionId}/providers/Microsoft.Somthing
  3. ResourceGroup Scope

    1. top level resource: parent_id = /subscriptions/{subscriptionId}/resourceGroups/{groupName}/ which is the id of a resource group
    2. child resource: parent_id = {its parent resource id}, the parent resource is a resource group scope resource, so it will starts with /subscriptions/{subscriptionId}/resourceGroups/{groupName}/providers/Microsoft.Something
  4. Extension Scope

    1. I think all extension resources are top level resource, so parent_id = {the target resource id}
  5. ManagementGroup Scope

    1. top level resource: parent_id = /providers/Microsoft.Management/managementGroups/{managementGroupName}/ which is the id of a management group
    2. child resource: parent_id = {its parent resource id}, the parent resource is a resource group scope resource, so it will starts with /providers/Microsoft.Management/managementGroups/{managementGroupName}/providers/Microsoft.Something

However, there still are some edge cases, like if the scope from bicep types is unknown, or a type is not in the bicep types. In those cases, we can't infer the correct scope from type, but if user uses parent_id following above rule, we can manage these resources.

ms-henglu commented 2 years ago

https://github.com/Azure/terraform-provider-azurerm-restapi/pull/42 is the implementation about above solution which supports other scopes resources without introducing new property.

I've added lots of tests to guarantee that a correct resource id can be built from parent_id name and type, also added e2e tests to manage resource group(subscription scope), resource lock(extension scope), and many common resources(resource group scope).

But I don't have permission to create resource over tenant scope and mgmt group scope, I'll do more tests.

ms-henglu commented 2 years ago

Here is a document about how to build resource id from parent id, name and type. https://github.com/Azure/terraform-provider-azurerm-restapi/blob/main/docs/resource_id.md

ms-henglu commented 2 years ago

This feature has been supported, so I'll close this issue.

PPACI commented 3 months ago

Hello It seems that the following code doesn't support extension on anything else than resource group. https://github.com/Azure/terraform-provider-azapi/blob/e53a2e48d676da9d01efea6eb240736f7d6374bc/internal/services/parse/resource.go#L193-L202

this means it would not be possible to create costallocationrules since it's a billingAccount extension.

I found the following workaround by abusing the validation code, but it's not pretty... Would it be possible to add other extension type?

resource "azapi_resource" "cost_allocation_rules" {
  for_each  = { for rule in var.cost_allocation_rules_resource_group : rule.sourceResourceGroupName => rule }
  type      = "costAllocationRules@2023-11-01" # As long as it's doesn't contain "/" it's fine
  name      = "Microsoft.CostManagement/costAllocationRules/${each.value["sourceResourceGroupName"]}-to-${data.azurerm_subscription.target.display_name}"
  parent_id = "/providers/Microsoft.Billing/billingAccounts/${var.billing_account_id}"

  /*
  case !strings.Contains(azureResourceType, "/"):
        // case 0: resource type is a provider type
        // avoid duplicated `/` if parent_id is tenant scope
        scopeId := parentId
        if parentId == "/" {
            scopeId = ""
        }
        azureResourceId = fmt.Sprintf("%s/providers/%s", scopeId, name)

but for this to work we have to pass an arbritary resource type
  and thus disable schema validation
  */
  schema_validation_enabled = false

  body = jsonencode({...})
}