diff --git a/azurerm/resource_arm_service_fabric_cluster.go b/azurerm/resource_arm_service_fabric_cluster.go index 50686d889797..b06733e3c013 100644 --- a/azurerm/resource_arm_service_fabric_cluster.go +++ b/azurerm/resource_arm_service_fabric_cluster.go @@ -78,6 +78,32 @@ func resourceArmServiceFabricCluster() *schema.Resource { Set: schema.HashString, }, + "azure_active_directory": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "tenant_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "cluster_application_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "client_application_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + }, + }, + }, + "certificate": { Type: schema.TypeList, Optional: true, @@ -288,6 +314,9 @@ func resourceArmServiceFabricClusterCreate(d *schema.ResourceData, meta interfac addOnFeaturesRaw := d.Get("add_on_features").(*schema.Set).List() addOnFeatures := expandServiceFabricClusterAddOnFeatures(addOnFeaturesRaw) + azureActiveDirectoryRaw := d.Get("azure_active_directory").([]interface{}) + azureActiveDirectory := expandServiceFabricClusterAzureActiveDirectory(azureActiveDirectoryRaw) + certificateRaw := d.Get("certificate").([]interface{}) certificate := expandServiceFabricClusterCertificate(certificateRaw) @@ -308,6 +337,7 @@ func resourceArmServiceFabricClusterCreate(d *schema.ResourceData, meta interfac Tags: expandTags(tags), ClusterProperties: &servicefabric.ClusterProperties{ AddOnFeatures: addOnFeatures, + AzureActiveDirectory: azureActiveDirectory, Certificate: certificate, ClientCertificateThumbprints: clientCertificateThumbprints, DiagnosticsStorageAccountConfig: diagnostics, @@ -445,6 +475,11 @@ func resourceArmServiceFabricClusterRead(d *schema.ResourceData, meta interface{ return fmt.Errorf("Error setting `add_on_features`: %+v", err) } + azureActiveDirectory := flattenServiceFabricClusterAzureActiveDirectory(props.AzureActiveDirectory) + if err := d.Set("azure_active_directory", azureActiveDirectory); err != nil { + return fmt.Errorf("Error setting `azure_active_directory`: %+v", err) + } + certificate := flattenServiceFabricClusterCertificate(props.Certificate) if err := d.Set("certificate", certificate); err != nil { return fmt.Errorf("Error setting `certificate`: %+v", err) @@ -509,6 +544,49 @@ func expandServiceFabricClusterAddOnFeatures(input []interface{}) *[]string { return &output } +func expandServiceFabricClusterAzureActiveDirectory(input []interface{}) *servicefabric.AzureActiveDirectory { + if len(input) == 0 { + return nil + } + + v := input[0].(map[string]interface{}) + + tenantId := v["tenant_id"].(string) + clusterApplication := v["cluster_application_id"].(string) + clientApplication := v["client_application_id"].(string) + + config := servicefabric.AzureActiveDirectory{ + TenantID: utils.String(tenantId), + ClusterApplication: utils.String(clusterApplication), + ClientApplication: utils.String(clientApplication), + } + return &config +} + +func flattenServiceFabricClusterAzureActiveDirectory(input *servicefabric.AzureActiveDirectory) []interface{} { + results := make([]interface{}, 0) + + if v := input; v != nil { + output := make(map[string]interface{}) + + if name := v.TenantID; name != nil { + output["tenant_id"] = *name + } + + if name := v.ClusterApplication; name != nil { + output["cluster_application_id"] = *name + } + + if endpoint := v.ClientApplication; endpoint != nil { + output["client_application_id"] = *endpoint + } + + results = append(results, output) + } + + return results +} + func flattenServiceFabricClusterAddOnFeatures(input *[]string) []interface{} { output := make([]interface{}, 0) diff --git a/azurerm/resource_arm_service_fabric_cluster_test.go b/azurerm/resource_arm_service_fabric_cluster_test.go index fd8c6ae44474..63c0b7c1faaa 100644 --- a/azurerm/resource_arm_service_fabric_cluster_test.go +++ b/azurerm/resource_arm_service_fabric_cluster_test.go @@ -29,6 +29,7 @@ func TestAccAzureRMServiceFabricCluster_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "add_on_features.#", "0"), resource.TestCheckResourceAttr(resourceName, "certificate.#", "0"), resource.TestCheckResourceAttr(resourceName, "client_certificate_thumbprint.#", "0"), + resource.TestCheckResourceAttr(resourceName, "azure_active_directory.#", "0"), resource.TestCheckResourceAttr(resourceName, "diagnostics_config.#", "0"), resource.TestCheckResourceAttr(resourceName, "node_type.#", "1"), resource.TestCheckResourceAttr(resourceName, "node_type.0.instance_count", "3"), @@ -234,6 +235,41 @@ func TestAccAzureRMServiceFabricCluster_readerAdminClientCertificateThumbprint(t }) } +func TestAccAzureRMServiceFabricCluster_azureActiveDirectory(t *testing.T) { + resourceName := "azurerm_service_fabric_cluster.test" + ri := acctest.RandInt() + location := testLocation() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMServiceFabricClusterDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMServiceFabricCluster_azureActiveDirectory(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMServiceFabricClusterExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "certificate.#", "1"), + resource.TestCheckResourceAttr(resourceName, "certificate.0.thumbprint", "33:41:DB:6C:F2:AF:72:C6:11:DF:3B:E3:72:1A:65:3A:F1:D4:3E:CD:50:F5:84:F8:28:79:3D:BE:91:03:C3:EE"), + resource.TestCheckResourceAttr(resourceName, "certificate.0.x509_store_name", "My"), + resource.TestCheckResourceAttr(resourceName, "azure_active_directory.#", "1"), + resource.TestCheckResourceAttrSet(resourceName, "azure_active_directory.0.tenant_id"), + resource.TestCheckResourceAttrSet(resourceName, "azure_active_directory.0.cluster_application_id"), + resource.TestCheckResourceAttrSet(resourceName, "azure_active_directory.0.client_application_id"), + resource.TestCheckResourceAttr(resourceName, "fabric_settings.0.name", "Security"), + resource.TestCheckResourceAttr(resourceName, "fabric_settings.0.parameters.ClusterProtectionLevel", "EncryptAndSign"), + resource.TestCheckResourceAttr(resourceName, "management_endpoint", "https://example:80"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func TestAccAzureRMServiceFabricCluster_diagnosticsConfig(t *testing.T) { resourceName := "azurerm_service_fabric_cluster.test" ri := acctest.RandInt() @@ -721,6 +757,63 @@ resource "azurerm_service_fabric_cluster" "test" { `, rInt, location, rInt) } +func testAccAzureRMServiceFabricCluster_azureActiveDirectory(rInt int, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +data "azurerm_client_config" "current" {} + +resource "azurerm_azuread_application" "test" { + name = "${azurerm_resource_group.test.name}-AAD" + homepage = "https://example:80/Explorer/index.html" + identifier_uris = ["https://acctestAAD-app"] + reply_urls = ["https://acctestAAD-app"] + available_to_other_tenants = false + oauth2_allow_implicit_flow = true +} + +resource "azurerm_service_fabric_cluster" "test" { + name = "acctest-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + reliability_level = "Bronze" + upgrade_mode = "Automatic" + vm_image = "Windows" + management_endpoint = "https://example:80" + + certificate { + thumbprint = "33:41:DB:6C:F2:AF:72:C6:11:DF:3B:E3:72:1A:65:3A:F1:D4:3E:CD:50:F5:84:F8:28:79:3D:BE:91:03:C3:EE" + x509_store_name = "My" + } + + azure_active_directory { + tenant_id = "${data.azurerm_client_config.current.tenant_id}" + cluster_application_id = "${azurerm_azuread_application.test.application_id}" + client_application_id = "00000000-0000-0000-0000-000000000000" + } + + fabric_settings { + name = "Security" + + parameters { + "ClusterProtectionLevel" = "EncryptAndSign" + } + } + + node_type { + name = "first" + instance_count = 3 + is_primary = true + client_endpoint_port = 2020 + http_endpoint_port = 80 + } +} +`, rInt, location, rInt) +} + func testAccAzureRMServiceFabricCluster_diagnosticsConfig(rInt int, rString, location string) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { diff --git a/website/docs/r/service_fabric_cluster.html.markdown b/website/docs/r/service_fabric_cluster.html.markdown index 330febf18a8b..76c6f3933a33 100644 --- a/website/docs/r/service_fabric_cluster.html.markdown +++ b/website/docs/r/service_fabric_cluster.html.markdown @@ -65,6 +65,8 @@ The following arguments are supported: * `add_on_features` - (Optional) A List of one or more features which should be enabled, such as `DnsService`. +* `azure_active_directory` - (Optional) An `azure_active_directory` block as defined below. Changing this forces a new resource to be created. + * `certificate` - (Optional) A `certificate` block as defined below. * `client_certificate_thumbprint` - (Optional) One or two `client_certificate_thumbprint` blocks as defined below. @@ -79,6 +81,16 @@ The following arguments are supported: --- +A `azure_active_directory` block supports the following: + +* `tenant_id` - (Required) The Azure Active Directory Tenant ID. Changing this forces a new resource to be created. + +* `cluster_application_id` - (Required) The Azure Active Directory Client ID which should be used for the Cluster Application. Changing this forces a new resource to be created. + +* `cluster_application_id` - (Required) The Azure Active Directory Client ID which should be used for the Client Application. Changing this forces a new resource to be created. + +--- + A `certificate` block supports the following: * `thumbprint` - (Required) The Thumbprint of the Certificate.