Skip to content

Commit

Permalink
Merge pull request #4204 from innovationnorway/appservice-ssl-bind
Browse files Browse the repository at this point in the history
`azurerm_app_service_custom_hostname_binding`: support for the `ssl_state` and `thumbprint` properties
  • Loading branch information
tombuildsstuff committed Oct 2, 2019
2 parents 6626124 + 076cc9c commit c82e300
Show file tree
Hide file tree
Showing 3 changed files with 181 additions and 0 deletions.
48 changes: 48 additions & 0 deletions azurerm/resource_arm_app_service_custom_hostname_binding.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import (

"github.com/Azure/azure-sdk-for-go/services/web/mgmt/2018-02-01/web"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/locks"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
Expand Down Expand Up @@ -38,6 +40,28 @@ func resourceArmAppServiceCustomHostnameBinding() *schema.Resource {
Required: true,
ForceNew: true,
},

"ssl_state": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
ValidateFunc: validation.StringInSlice([]string{
string(web.SslStateIPBasedEnabled),
string(web.SslStateSniEnabled),
}, false),
},

"thumbprint": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
ValidateFunc: validate.NoEmptyStrings,
},

"virtual_ip": {
Type: schema.TypeString,
Computed: true,
},
},
}
}
Expand All @@ -51,6 +75,8 @@ func resourceArmAppServiceCustomHostnameBindingCreate(d *schema.ResourceData, me
resourceGroup := d.Get("resource_group_name").(string)
appServiceName := d.Get("app_service_name").(string)
hostname := d.Get("hostname").(string)
sslState := d.Get("ssl_state").(string)
thumbprint := d.Get("thumbprint").(string)

locks.ByName(appServiceName, appServiceCustomHostnameBindingResourceName)
defer locks.UnlockByName(appServiceName, appServiceCustomHostnameBindingResourceName)
Expand All @@ -74,6 +100,22 @@ func resourceArmAppServiceCustomHostnameBindingCreate(d *schema.ResourceData, me
},
}

if sslState != "" {
if thumbprint == "" {
return fmt.Errorf("`thumbprint` must be specified when `ssl_state` is set")
}

properties.HostNameBindingProperties.SslState = web.SslState(sslState)
}

if thumbprint != "" {
if sslState == "" {
return fmt.Errorf("`ssl_state` must be specified when `thumbprint` is set")
}

properties.HostNameBindingProperties.Thumbprint = utils.String(thumbprint)
}

if _, err := client.CreateOrUpdateHostNameBinding(ctx, resourceGroup, appServiceName, hostname, properties); err != nil {
return err
}
Expand Down Expand Up @@ -118,6 +160,12 @@ func resourceArmAppServiceCustomHostnameBindingRead(d *schema.ResourceData, meta
d.Set("app_service_name", appServiceName)
d.Set("resource_group_name", resourceGroup)

if props := resp.HostNameBindingProperties; props != nil {
d.Set("ssl_state", props.SslState)
d.Set("thumbprint", props.Thumbprint)
d.Set("virtual_ip", props.VirtualIP)
}

return nil
}

Expand Down
125 changes: 125 additions & 0 deletions azurerm/resource_arm_app_service_custom_hostname_binding_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ func TestAccAzureRMAppServiceCustomHostnameBinding(t *testing.T) {
"basic": testAccAzureRMAppServiceCustomHostnameBinding_basic,
"multiple": testAccAzureRMAppServiceCustomHostnameBinding_multiple,
"requiresImport": testAccAzureRMAppServiceCustomHostnameBinding_requiresImport,
"ssl": testAccAzureRMAppServiceCustomHostnameBinding_ssl,
},
}

Expand Down Expand Up @@ -131,6 +132,32 @@ func testAccAzureRMAppServiceCustomHostnameBinding_multiple(t *testing.T, appSer
})
}

func testAccAzureRMAppServiceCustomHostnameBinding_ssl(t *testing.T, appServiceEnv, domainEnv string) {
resourceName := "azurerm_app_service_custom_hostname_binding.test"
ri := tf.AccRandTimeInt()
location := testLocation()
config := testAccAzureRMAppServiceCustomHostnameBinding_sslConfig(ri, location, appServiceEnv, domainEnv)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMAppServiceCustomHostnameBindingDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMAppServiceCustomHostnameBindingExists(resourceName),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func testCheckAzureRMAppServiceCustomHostnameBindingDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*ArmClient).web.AppServicesClient

Expand Down Expand Up @@ -244,3 +271,101 @@ resource "azurerm_app_service_custom_hostname_binding" "test2" {
}
`, template, altDomain)
}

func testAccAzureRMAppServiceCustomHostnameBinding_sslConfig(rInt int, location, appServiceName, domain string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "%s"
}
resource "azurerm_app_service_plan" "test" {
name = "acctestASP-%d"
location = "${azurerm_resource_group.test.location}"
resource_group_name = "${azurerm_resource_group.test.name}"
sku {
tier = "Standard"
size = "S1"
}
}
resource "azurerm_app_service" "test" {
name = "%s"
location = "${azurerm_resource_group.test.location}"
resource_group_name = "${azurerm_resource_group.test.name}"
app_service_plan_id = "${azurerm_app_service_plan.test.id}"
}
data "azurerm_client_config" "test" {}
resource "azurerm_key_vault" "test" {
name = "acct-%d"
location = "${azurerm_resource_group.test.location}"
resource_group_name = "${azurerm_resource_group.test.name}"
tenant_id = "${data.azurerm_client_config.test.tenant_id}"
sku_name = "standard"
access_policy {
tenant_id = "${data.azurerm_client_config.test.tenant_id}"
object_id = "${data.azurerm_client_config.test.service_principal_object_id}"
secret_permissions = ["delete", "get", "set"]
certificate_permissions = ["create", "delete", "get", "import"]
}
}
resource "azurerm_key_vault_certificate" "test" {
name = "acct-%d"
key_vault_id = "${azurerm_key_vault.test.id}"
certificate_policy {
issuer_parameters {
name = "Self"
}
key_properties {
exportable = true
key_size = 2048
key_type = "RSA"
reuse_key = true
}
secret_properties {
content_type = "application/x-pkcs12"
}
x509_certificate_properties {
extended_key_usage = ["1.3.6.1.5.5.7.3.1"]
key_usage = [
"digitalSignature",
"keyEncipherment",
]
subject = "CN=%s"
validity_in_months = 12
}
}
}
data "azurerm_key_vault_secret" "test" {
name = "${azurerm_key_vault_certificate.test.name}"
key_vault_id = "${azurerm_key_vault.test.id}"
}
resource "azurerm_app_service_certificate" "test" {
name = "acctestCert-%d"
resource_group_name = "${azurerm_resource_group.test.name}"
location = "${azurerm_resource_group.test.location}"
pfx_blob = "${data.azurerm_key_vault_secret.test.value}"
}
resource "azurerm_app_service_custom_hostname_binding" "test" {
hostname = "%s"
app_service_name = "${azurerm_app_service.test.name}"
resource_group_name = "${azurerm_resource_group.test.name}"
ssl_state = "SniEnabled"
thumbprint = "${azurerm_app_service_certificate.test.thumbprint}"
}
`, rInt, location, rInt, appServiceName, rInt, rInt, domain, rInt, domain)
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,20 @@ The following arguments are supported:

* `resource_group_name` - (Required) The name of the resource group in which the App Service exists. Changing this forces a new resource to be created.

* `ssl_state` - (Optional) The SSL type. Possible values are `IpBasedEnabled` and `SniEnabled`. Changing this forces a new resource to be created.

* `thumbprint` - (Optional) The SSL certificate thumbprint. Changing this forces a new resource to be created.

-> **NOTE:** `thumbprint` must be specified when `ssl_state` is set.

## Attributes Reference

The following attributes are exported:

* `id` - The ID of the App Service Custom Hostname Binding

* `virtual_ip` - The virtual IP address assigned to the hostname if IP based SSL is enabled.

## Import

App Service Custom Hostname Bindings can be imported using the `resource id`, e.g.
Expand Down

0 comments on commit c82e300

Please sign in to comment.