diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..686e5e7a --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,10 @@ +# Microsoft Open Source Code of Conduct + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). + +Resources: + +- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) +- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) +- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns +- Employees can reach out at [aka.ms/opensource/moderation-support](https://aka.ms/opensource/moderation-support) diff --git a/quickstart/101-azure-container-app/main.tf b/quickstart/101-azure-container-app/main.tf new file mode 100644 index 00000000..313b80a1 --- /dev/null +++ b/quickstart/101-azure-container-app/main.tf @@ -0,0 +1,86 @@ +data "azurerm_client_config" "current" {} + +# Generate random resource group name +resource "random_pet" "rg_name" { + prefix = var.resource_group_name_prefix +} + +resource "azurerm_resource_group" "rg" { + location = var.resource_group_location + name = random_pet.rg_name.id +} + +# Generate random value for the log analytics workspace name +resource "random_string" "log_analytics_workspace_name" { + length = 8 + lower = true + numeric = false + special = false + upper = false +} + +resource "azurerm_log_analytics_workspace" "log_analytics_workspace" { + resource_group_name = azurerm_resource_group.rg.name + location = azurerm_resource_group.rg.location + + name = random_string.log_analytics_workspace_name.result + + sku = var.log_analytics_workspace_sku + retention_in_days = var.log_analytics_workspace_retention_in_days +} + +# Generate random value for the container app environment name +resource "random_string" "container_app_environment_name" { + length = 8 + lower = true + numeric = false + special = false + upper = false +} + +resource "azurerm_container_app_environment" "container_app_environment" { + resource_group_name = azurerm_resource_group.rg.name + location = azurerm_resource_group.rg.location + + name = random_string.container_app_environment_name.result + + log_analytics_workspace_id = azurerm_log_analytics_workspace.log_analytics_workspace.id +} + +# Generate random value for the container app name +resource "random_string" "container_app_name" { + length = 8 + lower = true + numeric = false + special = false + upper = false +} + +resource "azurerm_container_app" "container_app" { + resource_group_name = azurerm_resource_group.rg.name + + name = random_string.container_app_name.result + container_app_environment_id = azurerm_container_app_environment.container_app_environment.id + + revision_mode = var.container_app_revision_mode + + ingress { + allow_insecure_connections = false + external_enabled = true + target_port = 80 + + traffic_weight { + latest_revision = true + percentage = 100 + } + } + + template { + container { + name = var.container_name + image = var.container_image + cpu = var.container_cpu + memory = var.container_memory + } + } +} \ No newline at end of file diff --git a/quickstart/101-azure-container-app/outputs.tf b/quickstart/101-azure-container-app/outputs.tf new file mode 100644 index 00000000..a7ffe99f --- /dev/null +++ b/quickstart/101-azure-container-app/outputs.tf @@ -0,0 +1,15 @@ +output "resource_group_name" { + value = azurerm_resource_group.rg.name +} + +output "log_analytics_workspace_name" { + value = azurerm_log_analytics_workspace.log_analytics_workspace.name +} + +output "container_app_environment_name" { + value = azurerm_container_app_environment.container_app_environment.name +} + +output "container_app_name" { + value = azurerm_container_app.container_app.name +} \ No newline at end of file diff --git a/quickstart/101-azure-container-app/providers.tf b/quickstart/101-azure-container-app/providers.tf new file mode 100644 index 00000000..0d51fc35 --- /dev/null +++ b/quickstart/101-azure-container-app/providers.tf @@ -0,0 +1,19 @@ +terraform { + required_version = ">=1.0" + + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~>3.0" + } + + random = { + source = "hashicorp/random" + version = "~>3.0" + } + } +} + +provider "azurerm" { + features {} +} diff --git a/quickstart/101-azure-container-app/readme.md b/quickstart/101-azure-container-app/readme.md new file mode 100644 index 00000000..2a576d4d --- /dev/null +++ b/quickstart/101-azure-container-app/readme.md @@ -0,0 +1,24 @@ +# Azure Container App Environment with Container App + +This template deploys an [Azure Container App Environment](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/container_app_environment) with [Azure Container App](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/container_app). +## Terraform resource types + +- [random_pet](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) +- [azurerm_resource_group](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group) +- [random_string](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) +- [azurerm_container_app_environment](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/container_app_environment) +- [azurerm_container_app](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/container_app) + +## Variables + +| Name | Description | Default | +|-|-|-| +| `resource_group_name_prefix` | Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription. | rg | +| `resource_group_location` | Location of the resource group. | eastus | +| `log_analytics_workspace_sku` | Log analytics workspace sku| PerGB2018 | +| `log_analytics_workspace_retention_in_days` | Log analytics workspace retention in days | 30 | +| `container_app_revision_mode` | Container app revision mode | Single | +| `container_name` | Container name | examplecontainerapp | +| `container_image` | Container image | mcr.microsoft.com/azuredocs/containerapps-helloworld:latest | +| `container_cpu` | Container cpu | 0.25 | +| `container_memory` | Container memory | 0.5Gi | \ No newline at end of file diff --git a/quickstart/101-azure-container-app/variables.tf b/quickstart/101-azure-container-app/variables.tf new file mode 100644 index 00000000..1f25a2f4 --- /dev/null +++ b/quickstart/101-azure-container-app/variables.tf @@ -0,0 +1,53 @@ +variable "resource_group_location" { + type = string + description = "Location of the resource group." + default = "eastus" +} + +variable "resource_group_name_prefix" { + type = string + description = "Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription." + default = "rg" +} + +variable "log_analytics_workspace_sku" { + type = string + description = "Log analytics workspace sku" + default = "PerGB2018" +} + +variable "log_analytics_workspace_retention_in_days" { + type = number + description = "Log analytics workspace retention in days" + default = 30 +} + +variable "container_app_revision_mode" { + type = string + description = "Container app revision mode" + default = "Single" +} + +variable "container_name" { + type = string + description = "Container name" + default = "examplecontainerapp" +} + +variable "container_image" { + type = string + description = "Container image" + default = "mcr.microsoft.com/azuredocs/containerapps-helloworld:latest" +} + +variable "container_cpu" { + type = number + description = "Container cpu" + default = 0.25 +} + +variable "container_memory" { + type = string + description = "Container memory" + default = "0.5Gi" +} \ No newline at end of file diff --git a/quickstart/201-private-link-iothub-builtin-endpoint/main.tf b/quickstart/201-private-link-iothub-builtin-endpoint/main.tf new file mode 100644 index 00000000..55617248 --- /dev/null +++ b/quickstart/201-private-link-iothub-builtin-endpoint/main.tf @@ -0,0 +1,65 @@ +resource "random_string" "suffix" { + length = 5 + special = false + upper = false +} + +resource "azurerm_resource_group" "rg" { + name = "rg-iothub-${random_string.suffix.result}" + location = var.location +} + +resource "azurerm_iothub" "iothub" { + name = "iothub-${random_string.suffix.result}" + resource_group_name = azurerm_resource_group.rg.name + location = azurerm_resource_group.rg.location + public_network_access_enabled = false + + sku { + name = "S1" + capacity = 1 + } + + cloud_to_device { + max_delivery_count = 30 + default_ttl = "PT1H" + feedback { + time_to_live = "PT1H10M" + max_delivery_count = 15 + lock_duration = "PT30S" + } + } + +} + +resource "azurerm_iothub_shared_access_policy" "iothub_policy" { + name = "iothub-policy" + resource_group_name = azurerm_resource_group.rg.name + iothub_name = azurerm_iothub.iothub.name + + registry_read = true + registry_write = true + service_connect = true + + depends_on = [azurerm_private_endpoint.iothub] +} + +resource "azurerm_iothub_dps" "dps" { + name = "test-device-${random_string.suffix.result}" + resource_group_name = azurerm_resource_group.rg.name + location = azurerm_resource_group.rg.location + allocation_policy = "Hashed" + public_network_access_enabled = false + + sku { + name = "S1" + capacity = "1" + } + + linked_hub { + connection_string = azurerm_iothub_shared_access_policy.iothub_policy.primary_connection_string + location = azurerm_resource_group.rg.location + allocation_weight = 150 + apply_allocation_policy = true + } +} \ No newline at end of file diff --git a/quickstart/201-private-link-iothub-builtin-endpoint/network.tf b/quickstart/201-private-link-iothub-builtin-endpoint/network.tf new file mode 100644 index 00000000..8ba36ca0 --- /dev/null +++ b/quickstart/201-private-link-iothub-builtin-endpoint/network.tf @@ -0,0 +1,99 @@ +resource "azurerm_virtual_network" "vnet" { + name = "iothub-vnet-${random_string.suffix.result}" + address_space = [var.vnet_address_space] + location = azurerm_resource_group.rg.location + resource_group_name = azurerm_resource_group.rg.name +} + +resource "azurerm_subnet" "snet" { + name = "iothub-snet-${random_string.suffix.result}" + resource_group_name = azurerm_resource_group.rg.name + virtual_network_name = azurerm_virtual_network.vnet.name + address_prefixes = [var.iothub_subnet_address_space] +} + +## Private DNS Zone +resource "azurerm_private_dns_zone" "iothub" { + name = "privatelink.azure-devices.net" + resource_group_name = azurerm_resource_group.rg.name +} + +resource "azurerm_private_dns_zone" "eventhub" { + name = "privatelink.servicebus.windows.net" + resource_group_name = azurerm_resource_group.rg.name +} + +resource "azurerm_private_dns_zone" "dps" { + name = "privatelink.azure-devices-provisioning.net" + resource_group_name = azurerm_resource_group.rg.name +} + +resource "azurerm_private_dns_zone_virtual_network_link" "iothub" { + name = "vnet-link-iothub-${random_string.suffix.result}" + resource_group_name = azurerm_resource_group.rg.name + private_dns_zone_name = azurerm_private_dns_zone.iothub.name + virtual_network_id = azurerm_virtual_network.vnet.id +} + +resource "azurerm_private_dns_zone_virtual_network_link" "eventhub" { + name = "vnet-link-eventhub-${random_string.suffix.result}" + resource_group_name = azurerm_resource_group.rg.name + private_dns_zone_name = azurerm_private_dns_zone.eventhub.name + virtual_network_id = azurerm_virtual_network.vnet.id +} + +resource "azurerm_private_dns_zone_virtual_network_link" "dps" { + name = "vnet-link-dps-${random_string.suffix.result}" + resource_group_name = azurerm_resource_group.rg.name + private_dns_zone_name = azurerm_private_dns_zone.dps.name + virtual_network_id = azurerm_virtual_network.vnet.id +} + +## Private Endpoint +resource "azurerm_private_endpoint" "iothub" { + name = "pep-iothub-${random_string.suffix.result}" + location = azurerm_resource_group.rg.location + resource_group_name = azurerm_resource_group.rg.name + subnet_id = azurerm_subnet.snet.id + + private_service_connection { + name = "psc-iothub-${random_string.suffix.result}" + private_connection_resource_id = azurerm_iothub.iothub.id + subresource_names = ["iotHub"] + is_manual_connection = false + } + + private_dns_zone_group { + name = "privateDNSZoneGroup" + private_dns_zone_ids = [azurerm_private_dns_zone.iothub.id] + } + +} + +resource "azurerm_private_endpoint" "dps" { + name = "pep-dps-${random_string.suffix.result}" + location = azurerm_resource_group.rg.location + resource_group_name = azurerm_resource_group.rg.name + subnet_id = azurerm_subnet.snet.id + + private_service_connection { + name = "psc-iothub-${random_string.suffix.result}" + private_connection_resource_id = azurerm_iothub_dps.dps.id + subresource_names = ["iotDps"] + is_manual_connection = false + } + + private_dns_zone_group { + name = "privateDNSZoneGroup" + private_dns_zone_ids = [azurerm_private_dns_zone.dps.id] + } +} + +## Add DNS Record for Built-in eventhub +resource "azurerm_private_dns_a_record" "eventhub" { + name = azurerm_iothub.iothub.event_hub_events_namespace + ttl = 10000 + zone_name = azurerm_private_dns_zone.eventhub.name + resource_group_name = azurerm_resource_group.rg.name + records = [azurerm_private_endpoint.iothub.custom_dns_configs[0].ip_addresses[0]] +} \ No newline at end of file diff --git a/quickstart/201-private-link-iothub-builtin-endpoint/outputs.tf b/quickstart/201-private-link-iothub-builtin-endpoint/outputs.tf new file mode 100644 index 00000000..48032f9a --- /dev/null +++ b/quickstart/201-private-link-iothub-builtin-endpoint/outputs.tf @@ -0,0 +1,19 @@ +output "resource_group_name" { + description = "The name of the created resource group." + value = azurerm_resource_group.rg.name +} + +output "virtual_network_name" { + description = "The name of the created virtual network." + value = azurerm_virtual_network.vnet.name +} + +output "iothub_subnet_name" { + description = "The name of the created subnet for iothub." + value = azurerm_subnet.snet.name +} + +output "iothub_name" { + description = "The name of the created iothub." + value = azurerm_subnet.snet.name +} \ No newline at end of file diff --git a/quickstart/201-private-link-iothub-builtin-endpoint/provider.tf b/quickstart/201-private-link-iothub-builtin-endpoint/provider.tf new file mode 100644 index 00000000..e5c0bc1a --- /dev/null +++ b/quickstart/201-private-link-iothub-builtin-endpoint/provider.tf @@ -0,0 +1,14 @@ +terraform { + required_version = ">= 1.2" + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = ">= 3.35.0, < 4.0.0" + } + } +} + +provider "azurerm" { + features { + } +} \ No newline at end of file diff --git a/quickstart/201-private-link-iothub-builtin-endpoint/readme.md b/quickstart/201-private-link-iothub-builtin-endpoint/readme.md new file mode 100644 index 00000000..3957b09c --- /dev/null +++ b/quickstart/201-private-link-iothub-builtin-endpoint/readme.md @@ -0,0 +1,27 @@ +# Azure Private Link for IoT Hub and IoT Hub Device Provisioning Service + +This template specifies configuration for deploying [Azure IoT Hub](https://learn.microsoft.com/azure/iot-hub/) and [Azure IoT Hub Device Provisioning Service](https://learn.microsoft.com/azure/iot-dps/) services in a Virtual Network. + +In addition to deploying the two resources above, it deploys the necessary network components required to set up private network connectivity between IoT Hub, the IoT Hub's built-in eventhub endpoint and the Azure DPS using [Azure Private Link Service](https://docs.microsoft.com/en-us/azure/private-link/). + +## Terraform resource types + +* [random_string](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) +* [azurerm_resource_group](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group) +* [azurerm_iothub](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/iothub) +* [azurerm_iothub_shared_access_policy](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/iothub_shared_access_policy) +* [azurerm_iothub_dps](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/iothub_dps) +* [azurerm_virtual_network](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/virtual_network) +* [azurerm_subnet](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/subnet) +* [azurerm_private_dns_zone](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/private_dns_zone) +* [azurerm_private_dns_zone_virtual_network_link](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/private_dns_zone_virtual_network_link) +* [azurerm_private_endpoint](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/private_endpoint) + + +## Variables + +| Name | Description | Default | +| ---- | ----------- | ------- | +| `location` | Location of the resource group. | `westeurope` | +| `vnet_address_space` | Private IP address range of the virtual network | `10.0.0.0/16` | +| `iothub_subnet_address_space` | Private IP address of the iothub subnet | `10.0.3.0/24` | \ No newline at end of file diff --git a/quickstart/201-private-link-iothub-builtin-endpoint/variables.tf b/quickstart/201-private-link-iothub-builtin-endpoint/variables.tf new file mode 100644 index 00000000..3847b38b --- /dev/null +++ b/quickstart/201-private-link-iothub-builtin-endpoint/variables.tf @@ -0,0 +1,17 @@ +variable "location" { + type = string + default = "westeurope" + description = "Location of the resource group" +} + +variable "vnet_address_space" { + type = string + default = "10.0.0.0/16" + description = "Address range of the virtual network" +} + +variable "iothub_subnet_address_space" { + type = string + default = "10.0.3.0/24" + description = "Address range of the subnet containing the iothub" +} \ No newline at end of file