From dfe7f855cd8d57b345b1e5235ea1d56df06a9bf0 Mon Sep 17 00:00:00 2001 From: Moritz Sanft <58110325+stdoutput@users.noreply.github.com> Date: Wed, 16 Nov 2022 20:19:10 +0100 Subject: [PATCH] AB#2578 Implement Azure IAM in terraform (#562) * AB#2578 Azure IAM init * AB#2578 Fixed application owner privileges, added docs * Add all supported providers to TF lockfile * Using service principal for role assignment in cluster resource group Co-authored-by: Malte Poll * Rephrased header for Azure Co-authored-by: Malte Poll * Registry -> Registration typo Co-authored-by: Malte Poll * Download lockfile * File name casing Co-authored-by: Malte Poll --- hack/terraform/azure/iam/.terraform.lock.hcl | 50 ++++++++++++ hack/terraform/azure/iam/README.md | 37 +++++++++ hack/terraform/azure/iam/main.tf | 84 ++++++++++++++++++++ hack/terraform/azure/iam/output.tf | 28 +++++++ hack/terraform/azure/iam/readme.md | 37 +++++++++ hack/terraform/azure/iam/variables.tf | 14 ++++ 6 files changed, 250 insertions(+) create mode 100644 hack/terraform/azure/iam/.terraform.lock.hcl create mode 100644 hack/terraform/azure/iam/README.md create mode 100644 hack/terraform/azure/iam/main.tf create mode 100644 hack/terraform/azure/iam/output.tf create mode 100644 hack/terraform/azure/iam/readme.md create mode 100644 hack/terraform/azure/iam/variables.tf diff --git a/hack/terraform/azure/iam/.terraform.lock.hcl b/hack/terraform/azure/iam/.terraform.lock.hcl new file mode 100644 index 000000000..96af9f788 --- /dev/null +++ b/hack/terraform/azure/iam/.terraform.lock.hcl @@ -0,0 +1,50 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/azuread" { + version = "2.30.0" + constraints = "~> 2.30.0" + hashes = [ + "h1:MimDtBEnmdMwbriZQzga/kCjDZ1G0+QLVQjrYdBEpdc=", + "h1:Uw4TcmJBEJ71h+oCwwidlkk5jFpyFRDPAFCMs/bT/cw=", + "h1:WnSPiREAFwnBUKREokMdHQ8Cjs47MzvS9pG8VS1ktec=", + "h1:eMxghqjmi2DCdps3dgo2SVOUfebzCatA3OdsTowlqXw=", + "h1:xzNKb+lWPsBTxJiaAJ8ECZnY+D6QNM9tA1qpEncIba0=", + "zh:1c3e89cf19118fc07d7b04257251fc9897e722c16e0a0df7b07fcd261f8c12e7", + "zh:2e62c193030e04ebb10cc0526119cf69824bf2d7e4ea5a2f45bd5d5fb7221d36", + "zh:2f3c7a35257332d68b778cefc5201a5f044e4914dd03794a4da662ddfe756483", + "zh:35d0d3a1b58fdb8b8c4462d6b7e7016042da43ea9cc734ce897f52a73407d9b0", + "zh:47ede0cd0206ec953d40bf4a80aa6e59af64e26cbbd877614ac424533dbb693b", + "zh:48c190307d4d42ea67c9b8cc544025024753f46cef6ea64db84735e7055a72da", + "zh:6fff9b2c6a962252a70a15b400147789ab369b35a781e9d21cce3804b04d29af", + "zh:7646980cf3438bff29c91ffedb74458febbb00a996638751fbd204ab1c628c9b", + "zh:77aa2fa7ca6d5446afa71d4ff83cb87b70a2f3b72110fc442c339e8e710b2928", + "zh:e20b2b2c37175b89dd0db058a096544d448032e28e3b56e2db368343533a9684", + "zh:eab175b1dfe9865ad9404dccb6d5542899f8c435095aa7c679314b811c717ce7", + "zh:efc862bd78c55d2ff089729e2a34c1831ab4b0644fc11b36ee4ebed00a4797ba", + ] +} + +provider "registry.terraform.io/hashicorp/azurerm" { + version = "3.31.0" + constraints = "~> 3.31.0" + hashes = [ + "h1:AXTMOUd/zMPymRuNeMb/wCzk9IabtHEW7cHwEghqmhc=", + "h1:HdMwAeU+yBk0+3XvFY5v1BkLX+o0ImrfbKamHKO9fmQ=", + "h1:TQtkrjZb0IT9SzzrjJ/gGDiMV0L/rmlR+LmJvmRzBYA=", + "h1:fBDej98yLWwuL3fPrMrwF9Wu+0To2x8EHDEGKH75iOY=", + "h1:zc5rG3g3DUeQQEYpCfqm0tCAlfqxeXc74iQ95EgDv/0=", + "zh:1b61b26373bbb06e811e4ccb762651354d776db574ec904ac32835c98322ab98", + "zh:2ccea8876e54127e16729c09e9c59d164abc2a600230d3fc8331c459f91187af", + "zh:300f35a16f08a19eed08708561ecca044bc570d91e7f863f2b203c78e9df3a5f", + "zh:4e77936cbf555ea068a63095072ad7b636b598da02629375925f8ac539313f96", + "zh:63486a678e9e536a3a996dd2698b7d39d3b65d83a79e14b5520d5e26bde76d47", + "zh:8c620e70cae53b7c9ed923596d441fa5f09ff50bd1379b936e4a88211de86951", + "zh:91cc1b9bc3dfcadfe40750872baf254a8b1f715e2784e3f323edcfebfe5a4012", + "zh:b0b4c3064a58f831ad7ee36baee9bb18fc24cab8ca76902fec8bbc95aefffadf", + "zh:b70ea503c093d6d4fbbcd064c93a2139c8424a6ade6a7d9d869cd7c367f0b050", + "zh:d9738184fccca96bec3ded26c2e10c104423330be25a473d4e5e383b2161cdfe", + "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", + "zh:fcf1630b47bfae8e9834390b1a5cf4f6fd9ff0cc1ca596e6b60e9327db7529f4", + ] +} diff --git a/hack/terraform/azure/iam/README.md b/hack/terraform/azure/iam/README.md new file mode 100644 index 000000000..8f323d3bd --- /dev/null +++ b/hack/terraform/azure/iam/README.md @@ -0,0 +1,37 @@ +# Terraform Azure IAM creation + +This terraform configuration creates the necessary Azure resources that need to be available to host a Constellation cluster. + +You can create the resources with the following commands: +```sh +mkdir constellation_azure_iam +cd constellation_azure_iam +curl --remote-name-all https://raw.githubusercontent.com/edgelesssys/constellation/main/hack/terraform/azure/iam/{main.tf,output.tf,variables.tf,.terraform.lock.hcl} +terraform init +terraform apply +``` + +The following terraform output values are available (with their corresponding keys in the Constellation configuration file): +- `subscription_id` (subscription) +- `tenant_id` (tenant) +- `region` (location) +- `base_resource_group_name` (resourceGroup) +- `application_id` (appClientID) +- `uami_id` (userAssignedIdentity) +- `application_client_secret_value` (clientSecretValue) - **Sensitive Value** + +You can either get the profile names from the Terraform output and manually add them to your Constellation configuration file according to our [Documentation](https://docs.edgeless.systems/constellation/getting-started/first-steps). +Or you can do this with a `yq` command: +```sh +yq -i " + .provider.azure.subscription = $(terraform output subscription_id) | + .provider.azure.tenant = $(terraform output tenant_id) | + .provider.azure.location = $(terraform output region) | + .provider.azure.resourceGroup = $(terraform output base_resource_group_name) | + .provider.azure.appClientID = $(terraform output application_id) | + .provider.azure.userAssignedIdentity = $(terraform output uami_id) | + .provider.azure.clientSecretValue = $(terraform output application_client_secret_value) + " path/to/constellation-conf.yaml +``` + +Where `path/to/constellation-conf.yaml` is the path to your Constellation configuration file. diff --git a/hack/terraform/azure/iam/main.tf b/hack/terraform/azure/iam/main.tf new file mode 100644 index 000000000..4f24552e1 --- /dev/null +++ b/hack/terraform/azure/iam/main.tf @@ -0,0 +1,84 @@ +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 3.31.0" + } + azuread = { + source = "hashicorp/azuread" + version = "~> 2.30.0" + } + } +} + +# Configure Azure resource management provider +provider "azurerm" { + features {} +} + +# Configure Azure active directory provider +provider "azuread" { + tenant_id = data.azurerm_subscription.current.tenant_id +} + +# Access current subscription (available via Azure CLI) +data "azurerm_subscription" "current" {} + +# # Access current AzureAD configuration +data "azuread_client_config" "current" {} + +# Create base resource group +resource "azurerm_resource_group" "base_resource_group" { + name = var.resource_group_name + location = var.region +} + +# Create identity resource group +resource "azurerm_resource_group" "identity_resource_group" { + name = "${var.resource_group_name}-identity" + location = var.region +} + +# Create managed identity +resource "azurerm_user_assigned_identity" "identity_uami" { + location = var.region + name = var.service_principal_name + resource_group_name = azurerm_resource_group.identity_resource_group.name +} + +# Assign roles to managed identity +resource "azurerm_role_assignment" "virtual_machine_contributor_role" { + scope = "/subscriptions/${data.azurerm_subscription.current.subscription_id}/resourceGroups/${var.resource_group_name}" + role_definition_name = "Virtual Machine Contributor" + principal_id = azurerm_user_assigned_identity.identity_uami.principal_id +} + +resource "azurerm_role_assignment" "application_insights_component_contributor_role" { + scope = "/subscriptions/${data.azurerm_subscription.current.subscription_id}/resourceGroups/${var.resource_group_name}" + role_definition_name = "Application Insights Component Contributor" + principal_id = azurerm_user_assigned_identity.identity_uami.principal_id +} + +# Create application registration +resource "azuread_application" "base_application" { + display_name = "${var.resource_group_name}-application" + owners = [data.azuread_client_config.current.object_id] +} + +resource "azuread_service_principal" "application_principal" { + application_id = azuread_application.base_application.application_id + app_role_assignment_required = false + owners = [data.azuread_client_config.current.object_id] +} + +# Set identity as base resource group owner +resource "azurerm_role_assignment" "owner_role" { + scope = "/subscriptions/${data.azurerm_subscription.current.subscription_id}/resourceGroups/${var.resource_group_name}" + role_definition_name = "Owner" + principal_id = azuread_service_principal.application_principal.object_id +} + +# Create application secret (password) +resource "azuread_application_password" "base_application_secret" { + application_object_id = azuread_application.base_application.object_id +} diff --git a/hack/terraform/azure/iam/output.tf b/hack/terraform/azure/iam/output.tf new file mode 100644 index 000000000..9cf77abd0 --- /dev/null +++ b/hack/terraform/azure/iam/output.tf @@ -0,0 +1,28 @@ +output "subscription_id" { + value = data.azurerm_subscription.current.subscription_id +} + +output "tenant_id" { + value = data.azurerm_subscription.current.tenant_id +} + +output "region" { + value = var.region +} + +output "base_resource_group_name" { + value = var.resource_group_name +} + +output "application_id" { + value = azuread_application.base_application.application_id +} + +output "uami_id" { + value = azurerm_user_assigned_identity.identity_uami.id +} + +output "application_client_secret_value" { + value = azuread_application_password.base_application_secret.value + sensitive = true +} diff --git a/hack/terraform/azure/iam/readme.md b/hack/terraform/azure/iam/readme.md new file mode 100644 index 000000000..8f323d3bd --- /dev/null +++ b/hack/terraform/azure/iam/readme.md @@ -0,0 +1,37 @@ +# Terraform Azure IAM creation + +This terraform configuration creates the necessary Azure resources that need to be available to host a Constellation cluster. + +You can create the resources with the following commands: +```sh +mkdir constellation_azure_iam +cd constellation_azure_iam +curl --remote-name-all https://raw.githubusercontent.com/edgelesssys/constellation/main/hack/terraform/azure/iam/{main.tf,output.tf,variables.tf,.terraform.lock.hcl} +terraform init +terraform apply +``` + +The following terraform output values are available (with their corresponding keys in the Constellation configuration file): +- `subscription_id` (subscription) +- `tenant_id` (tenant) +- `region` (location) +- `base_resource_group_name` (resourceGroup) +- `application_id` (appClientID) +- `uami_id` (userAssignedIdentity) +- `application_client_secret_value` (clientSecretValue) - **Sensitive Value** + +You can either get the profile names from the Terraform output and manually add them to your Constellation configuration file according to our [Documentation](https://docs.edgeless.systems/constellation/getting-started/first-steps). +Or you can do this with a `yq` command: +```sh +yq -i " + .provider.azure.subscription = $(terraform output subscription_id) | + .provider.azure.tenant = $(terraform output tenant_id) | + .provider.azure.location = $(terraform output region) | + .provider.azure.resourceGroup = $(terraform output base_resource_group_name) | + .provider.azure.appClientID = $(terraform output application_id) | + .provider.azure.userAssignedIdentity = $(terraform output uami_id) | + .provider.azure.clientSecretValue = $(terraform output application_client_secret_value) + " path/to/constellation-conf.yaml +``` + +Where `path/to/constellation-conf.yaml` is the path to your Constellation configuration file. diff --git a/hack/terraform/azure/iam/variables.tf b/hack/terraform/azure/iam/variables.tf new file mode 100644 index 000000000..66b0f2724 --- /dev/null +++ b/hack/terraform/azure/iam/variables.tf @@ -0,0 +1,14 @@ +variable "resource_group_name" { + type = string + description = "Resource group name" +} + +variable "service_principal_name" { + type = string + description = "Service principal name" +} + +variable "region" { + type = string + description = "Azure resource location" +}