From 89a132ed9a2dea8e78fefab707f7c621285a8620 Mon Sep 17 00:00:00 2001 From: Graham Hayes Date: Thu, 3 Oct 2019 14:03:37 +0100 Subject: [PATCH] Add support for Azure Policy for AKS add on Signed-off-by: Graham Hayes --- azurerm/data_source_kubernetes_cluster.go | 27 ++++++++ .../data_source_kubernetes_cluster_test.go | 36 ++++++++++ azurerm/resource_arm_kubernetes_cluster.go | 39 +++++++++++ .../resource_arm_kubernetes_cluster_test.go | 65 +++++++++++++++++++ .../docs/d/kubernetes_cluster.html.markdown | 16 +++-- .../docs/r/kubernetes_cluster.html.markdown | 15 ++++- 6 files changed, 191 insertions(+), 7 deletions(-) diff --git a/azurerm/data_source_kubernetes_cluster.go b/azurerm/data_source_kubernetes_cluster.go index 5b3a00bd3e43..81098a7611e5 100644 --- a/azurerm/data_source_kubernetes_cluster.go +++ b/azurerm/data_source_kubernetes_cluster.go @@ -77,6 +77,19 @@ func dataSourceArmKubernetesCluster() *schema.Resource { }, }, }, + + "azure_policy": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Computed: true, + }, + }, + }, + }, }, }, }, @@ -622,6 +635,20 @@ func flattenKubernetesClusterDataSourceAddonProfiles(profile map[string]*contain } values["kube_dashboard"] = kubeDashboards + azurePolicies := make([]interface{}, 0) + if azurePolicy := profile["azurepolicy"]; azurePolicy != nil { + enabled := false + if enabledVal := azurePolicy.Enabled; enabledVal != nil { + enabled = *enabledVal + } + + output := map[string]interface{}{ + "enabled": enabled, + } + azurePolicies = append(azurePolicies, output) + } + values["azure_policy"] = azurePolicies + return []interface{}{values} } diff --git a/azurerm/data_source_kubernetes_cluster_test.go b/azurerm/data_source_kubernetes_cluster_test.go index bfef2b5d7904..9c7da7ce8c0b 100644 --- a/azurerm/data_source_kubernetes_cluster_test.go +++ b/azurerm/data_source_kubernetes_cluster_test.go @@ -416,6 +416,30 @@ func TestAccDataSourceAzureRMKubernetesCluster_addOnProfileKubeDashboard(t *test }) } +func TestAccDataSourceAzureRMKubernetesCluster_addOnProfileAzurePolicy(t *testing.T) { + resourceName := "azurerm_kubernetes_cluster.test" + ri := tf.AccRandTimeInt() + clientId := os.Getenv("ARM_CLIENT_ID") + clientSecret := os.Getenv("ARM_CLIENT_SECRET") + config := testAccDataSourceAzureRMKubernetesCluster_addOnProfileAzurePolicy(ri, clientId, clientSecret, testLocation()) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMKubernetesClusterDestroy, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMKubernetesClusterExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "addon_profile.0.azure_policy.#", "1"), + resource.TestCheckResourceAttr(resourceName, "addon_profile.0.azure_policy.0.enabled", "true"), + ), + }, + }, + }) +} + func TestAccDataSourceAzureRMKubernetesCluster_addOnProfileRouting(t *testing.T) { dataSourceName := "data.azurerm_kubernetes_cluster.test" ri := tf.AccRandTimeInt() @@ -693,6 +717,18 @@ data "azurerm_kubernetes_cluster" "test" { `, r) } +func testAccDataSourceAzureRMKubernetesCluster_addOnProfileAzurePolicy(rInt int, clientId string, clientSecret string, location string) string { + r := testAccAzureRMKubernetesCluster_addonProfileAzurePolicy(rInt, clientId, clientSecret, location) + return fmt.Sprintf(` +%s + +data "azurerm_kubernetes_cluster" "test" { + name = "${azurerm_kubernetes_cluster.test.name}" + resource_group_name = "${azurerm_kubernetes_cluster.test.resource_group_name}" +} +`, r) +} + func testAccDataSourceAzureRMKubernetesCluster_addOnProfileRouting(rInt int, clientId string, clientSecret string, location string) string { r := testAccAzureRMKubernetesCluster_addonProfileRouting(rInt, clientId, clientSecret, location) return fmt.Sprintf(` diff --git a/azurerm/resource_arm_kubernetes_cluster.go b/azurerm/resource_arm_kubernetes_cluster.go index 9759c8f16e84..50f4f17f664a 100644 --- a/azurerm/resource_arm_kubernetes_cluster.go +++ b/azurerm/resource_arm_kubernetes_cluster.go @@ -315,6 +315,20 @@ func resourceArmKubernetesCluster() *schema.Resource { }, }, }, + + "azure_policy": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + }, + }, + }, + }, }, }, }, @@ -1043,6 +1057,17 @@ func expandKubernetesClusterAddonProfiles(d *schema.ResourceData) map[string]*co } } + azurePolicy := profile["azure_policy"].([]interface{}) + if len(azurePolicy) > 0 && azurePolicy[0] != nil { + value := azurePolicy[0].(map[string]interface{}) + enabled := value["enabled"].(bool) + + addonProfiles["azurepolicy"] = &containerservice.ManagedClusterAddonProfile{ + Enabled: utils.Bool(enabled), + Config: nil, + } + } + return addonProfiles } @@ -1123,6 +1148,20 @@ func flattenKubernetesClusterAddonProfiles(profile map[string]*containerservice. } values["kube_dashboard"] = kubeDashboards + azurePolicies := make([]interface{}, 0) + if azurePolicy := profile["azurepolicy"]; azurePolicy != nil { + enabled := false + if enabledVal := azurePolicy.Enabled; enabledVal != nil { + enabled = *enabledVal + } + + output := map[string]interface{}{ + "enabled": enabled, + } + azurePolicies = append(azurePolicies, output) + } + values["azure_policy"] = azurePolicies + return []interface{}{values} } diff --git a/azurerm/resource_arm_kubernetes_cluster_test.go b/azurerm/resource_arm_kubernetes_cluster_test.go index 3ee78bdd04cb..d82924f5548c 100644 --- a/azurerm/resource_arm_kubernetes_cluster_test.go +++ b/azurerm/resource_arm_kubernetes_cluster_test.go @@ -439,6 +439,30 @@ func TestAccAzureRMKubernetesCluster_addonProfileKubeDashboard(t *testing.T) { }) } +func TestAccAzureRMKubernetesCluster_addonProfileAzurePolicy(t *testing.T) { + resourceName := "azurerm_kubernetes_cluster.test" + ri := tf.AccRandTimeInt() + clientId := os.Getenv("ARM_CLIENT_ID") + clientSecret := os.Getenv("ARM_CLIENT_SECRET") + config := testAccAzureRMKubernetesCluster_addonProfileAzurePolicy(ri, clientId, clientSecret, testLocation()) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMKubernetesClusterDestroy, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMKubernetesClusterExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "addon_profile.0.azure_policy.#", "1"), + resource.TestCheckResourceAttr(resourceName, "addon_profile.0.azure_policy.0.enabled", "true"), + ), + }, + }, + }) +} + func TestAccAzureRMKubernetesCluster_advancedNetworkingKubenet(t *testing.T) { resourceName := "azurerm_kubernetes_cluster.test" ri := tf.AccRandTimeInt() @@ -1532,6 +1556,47 @@ resource "azurerm_kubernetes_cluster" "test" { `, rInt, location, rInt, rInt, rInt, clientId, clientSecret) } +func testAccAzureRMKubernetesCluster_addonProfileAzurePolicy(rInt int, clientId string, clientSecret string, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_kubernetes_cluster" "test" { + name = "acctestaks%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + dns_prefix = "acctestaks%d" + + linux_profile { + admin_username = "acctestuser%d" + + ssh_key { + key_data = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCqaZoyiz1qbdOQ8xEf6uEu1cCwYowo5FHtsBhqLoDnnp7KUTEBN+L2NxRIfQ781rxV6Iq5jSav6b2Q8z5KiseOlvKA/RF2wqU0UPYqQviQhLmW6THTpmrv/YkUCuzxDpsH7DUDhZcwySLKVVe0Qm3+5N2Ta6UYH3lsDf9R9wTP2K/+vAnflKebuypNlmocIvakFWoZda18FOmsOoIVXQ8HWFNCuw9ZCunMSN62QGamCe3dL5cXlkgHYv7ekJE15IA9aOJcM7e90oeTqo+7HTcWfdu0qQqPWY5ujyMw/llas8tsXY85LFqRnr3gJ02bAscjc477+X+j/gkpFoN1QEmt terraform@demo.tld" + } + } + + agent_pool_profile { + name = "default" + count = "1" + vm_size = "Standard_DS2_v2" + } + + service_principal { + client_id = "%s" + client_secret = "%s" + } + + addon_profile { + azure_policy { + enabled = true + } + } +} +`, rInt, location, rInt, rInt, rInt, clientId, clientSecret) +} + func testAccAzureRMKubernetesCluster_upgrade(rInt int, location, clientId, clientSecret, version string) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { diff --git a/website/docs/d/kubernetes_cluster.html.markdown b/website/docs/d/kubernetes_cluster.html.markdown index 19b45f9100d5..30d78ce210a3 100644 --- a/website/docs/d/kubernetes_cluster.html.markdown +++ b/website/docs/d/kubernetes_cluster.html.markdown @@ -80,6 +80,8 @@ A `addon_profile` block exports the following: * `kube_dashboard` - A `kube_dashboard` block. +* `azure_policy` - A `azure_policy` block. + --- A `agent_pool_profile` block exports the following: @@ -90,11 +92,11 @@ A `agent_pool_profile` block exports the following: * `max_pods` - The maximum number of pods that can run on each agent. -* `availability_zones` - The availability zones used for the nodes. +* `availability_zones` - The availability zones used for the nodes. -* `enable_auto_scaling` - If the auto-scaler is enabled. +* `enable_auto_scaling` - If the auto-scaler is enabled. -* `min_count` - Minimum number of nodes for auto-scaling +* `min_count` - Minimum number of nodes for auto-scaling * `max_count` - Maximum number of nodes for auto-scaling @@ -199,7 +201,13 @@ A `oms_agent` block exports the following: A `kube_dashboard` block supports the following: -* `enabled` - (Required) Is the Kubernetes Dashboard enabled? +* `enabled` - (Required) Is the Kubernetes Dashboard enabled? + +--- + +A `azure_policy` block supports the following: + +* `enabled` - (Required) Is Azure Policy for Kubernetes enabled? --- diff --git a/website/docs/r/kubernetes_cluster.html.markdown b/website/docs/r/kubernetes_cluster.html.markdown index e70f4ae123bc..15fa28623a88 100644 --- a/website/docs/r/kubernetes_cluster.html.markdown +++ b/website/docs/r/kubernetes_cluster.html.markdown @@ -93,7 +93,7 @@ A `aci_connector_linux` block supports the following: ``` resource "azurerm_subnet" "virtual" { - + ... delegation { @@ -144,6 +144,9 @@ A `addon_profile` block supports the following: * `http_application_routing` - (Optional) A `http_application_routing` block. * `oms_agent` - (Optional) A `oms_agent` block. For more details, please visit [How to onboard Azure Monitor for containers](https://docs.microsoft.com/en-us/azure/monitoring/monitoring-container-insights-onboard). * `kube_dashboard` - (Optional) A `kube_dashboard` block. +* `azure_policy` - (Optional) A `azure_policy` block. For more details please visit [Understand Azure Policy for Azure Kubernetes Service](https://docs.microsoft.com/en-ie/azure/governance/policy/concepts/rego-for-aks) + +-> **NOTE**: Azure Policy for Azure Kubernetes Service is currently in preview and not available to subscriptions that have not [opted-in](https://docs.microsoft.com/en-us/azure/governance/policy/concepts/rego-for-aks?toc=/azure/aks/toc.json) to join `Azure Policy` preview. --- @@ -159,7 +162,7 @@ A `agent_pool_profile` block supports the following: * `enable_auto_scaling` - (Optional) Whether to enable [auto-scaler](https://docs.microsoft.com/en-us/azure/aks/cluster-autoscaler). Note that auto scaling feature requires the that the `type` is set to `VirtualMachineScaleSets` -* `min_count` - (Optional) Minimum number of nodes for auto-scaling +* `min_count` - (Optional) Minimum number of nodes for auto-scaling * `max_count` - (Optional) Maximum number of nodes for auto-scaling @@ -247,7 +250,13 @@ A `oms_agent` block supports the following: A `kube_dashboard` block supports the following: -* `enabled` - (Required) Is the Kubernetes Dashboard enabled? +* `enabled` - (Required) Is the Kubernetes Dashboard enabled? +--- + + +A `azure_policy` block supports the following: + +* `enabled` - (Required) Is the Azure Policy for Kubernetes Add On enabled? ---