Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

azurerm_app_service_certificate - support for hosting_environment_profile_id #7087

Merged
merged 8 commits into from Jun 16, 2020
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/base64"
"fmt"
"log"
"strings"
"time"

"github.com/Azure/azure-sdk-for-go/services/web/mgmt/2019-08-01/web"
Expand Down Expand Up @@ -73,6 +74,24 @@ func resourceArmAppServiceCertificate() *schema.Resource {
ConflictsWith: []string{"pfx_blob", "password"},
},

"hosting_environment": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"resource_group_name": {
Type: schema.TypeString,
Optional: true,
},
"environment_name": {
Type: schema.TypeString,
Optional: true,
},
},
},
},

"friendly_name": {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -130,6 +149,37 @@ func resourceArmAppServiceCertificateCreateUpdate(d *schema.ResourceData, meta i
pfxBlob := d.Get("pfx_blob").(string)
password := d.Get("password").(string)
keyVaultSecretId := d.Get("key_vault_secret_id").(string)
///////////
/// New ///
///////////
var hostingEnvironmentProfileId string
hostingEnvironment := d.Get("hosting_environment")
if hostingEnvironment != nil {
configs := hostingEnvironment.([]interface{})
if len(configs) < 1 {
return fmt.Errorf("For hosting environment resource_group_name and environment_name must be specified")
}

config := configs[0].(map[string]interface{})

if _, ok := config["resource_group_name"]; !ok {
return fmt.Errorf("For hosting_environment resource_group_name must be specified")
}
aseResourceGroup := config["resource_group_name"].(string)

if _, ok := config["environment_name"]; ok {
return fmt.Errorf("For hosting_environment environment_name must be specified")
}
aseName := config["environment_name"].(string)

subscriptionId := meta.(*clients.Client).Account.SubscriptionId

hostingEnvironmentProfileId = fmt.Sprintf(
"/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Web/hostingEnvironments/%s",
subscriptionId, aseResourceGroup, aseName)
}
///////////
///////////
t := d.Get("tags").(map[string]interface{})

if pfxBlob == "" && keyVaultSecretId == "" {
Expand Down Expand Up @@ -157,6 +207,12 @@ func resourceArmAppServiceCertificateCreateUpdate(d *schema.ResourceData, meta i
Tags: tags.Expand(t),
}

if len(hostingEnvironmentProfileId) > 0 {
certificate.CertificateProperties.HostingEnvironmentProfile = &web.HostingEnvironmentProfile{
ID: &hostingEnvironmentProfileId,
}
}

if pfxBlob != "" {
decodedPfxBlob, err := base64.StdEncoding.DecodeString(pfxBlob)
if err != nil {
Expand Down Expand Up @@ -237,6 +293,23 @@ func resourceArmAppServiceCertificateRead(d *schema.ResourceData, meta interface
d.Set("issue_date", props.IssueDate.Format(time.RFC3339))
d.Set("expiration_date", props.ExpirationDate.Format(time.RFC3339))
d.Set("thumbprint", props.Thumbprint)

if hep := props.HostingEnvironmentProfile; hep != nil {
configs := make([]interface{}, 0)
config := make(map[string]interface{})

idToks := strings.Split(*hep.ID, "/")
if len(idToks) != 8 {
return fmt.Errorf("Invalid format for hosting environment ID - Tokens Expected: 8, Tokens Actual: %d", len(idToks))
}
resourceGroupName := idToks[3]
aseName := idToks[7]

config["resource_group_name"] = resourceGroupName
config["environment_name"] = aseName
configs = append(configs, config)
d.Set("hosting_environment", configs)
}
}

return tags.FlattenAndSet(d, resp.Tags)
Expand Down
Expand Up @@ -139,6 +139,31 @@ func TestAccAzureRMAppServiceEnvironment_dedicatedResourceGroup(t *testing.T) {
})
}

func TestAccAzureRMAppServiceEnvironment_withCertificatePfx(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_app_service_environment", "test")
certData := acceptance.BuildTestData(t, "azurerm_app_service_certificate", "test")

aseRgName := fmt.Sprintf("acctestRG-%d", data.RandomInteger)
aseName := fmt.Sprintf("acctest-ase-%d", data.RandomInteger)
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acceptance.PreCheck(t) },
Providers: acceptance.SupportedProviders,
CheckDestroy: testCheckAzureRMAppServiceEnvironmentDestroy,
Steps: []resource.TestStep{
{
Config: testAccAzureRMAppServiceEnvironment_withCertificatePfx(data),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(certData.ResourceName,
"hosting_environment.0.resource_group_name", aseRgName),
resource.TestCheckResourceAttr(certData.ResourceName,
"hosting_environment.0.environment_name", aseName),
),
},
data.ImportStep(),
},
})
}

func testCheckAzureRMAppServiceEnvironmentExists(resourceName string) resource.TestCheckFunc {
return func(s *terraform.State) error {
client := acceptance.AzureProvider.Meta().(*clients.Client).Web.AppServiceEnvironmentsClient
Expand Down Expand Up @@ -271,6 +296,25 @@ resource "azurerm_app_service_environment" "test" {
`, template, data.RandomInteger, data.Locations.Secondary)
}

func testAccAzureRMAppServiceEnvironment_withCertificatePfx(data acceptance.TestData) string {
template := testAccAzureRMAppServiceEnvironment_basic(data)
return fmt.Sprintf(`
%s

resource "azurerm_app_service_certificate" "test" {
name = "acctest-cert-%d"
resource_group_name = azurerm_app_service_environment.test.resource_group_name
location = azurerm_resource_group.test.location
pfx_blob = filebase64("testdata/app_service_certificate.pfx")
password = "terraform"
hosting_environment = {
resource_group_name = azurerm_app_service_environment.test.resource_group_name
environment_name = "acctest-ase-%d"
}
}
`, template, data.RandomInteger, data.RandomInteger)
}

func testAccAzureRMAppServiceEnvironment_template(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
Expand Down
10 changes: 10 additions & 0 deletions website/docs/r/app_service_certificate.html.markdown
Expand Up @@ -47,6 +47,8 @@ The following arguments are supported:

* `password` - (Optional) The password to access the certificate's private key. Changing this forces a new resource to be created.

* `hosting_environment` - (Optional) A `hosting_environment` block as defined below. Must be specified when the certificate is for an App Service Environment hosted App Service.

* `key_vault_secret_id` - (Optional) The ID of the Key Vault secret. Changing this forces a new resource to be created.

-> **NOTE:** If using `key_vault_secret_id`, the WebApp Service Resource Principal ID `abfa0a7c-a6b6-4736-8310-5855508787cd` must have 'Secret -> get' and 'Certificate -> get' permissions on the Key Vault containing the certificate. (Source: [App Service Blog](https://azure.github.io/AppService/2016/05/24/Deploying-Azure-Web-App-Certificate-through-Key-Vault.html)) If you use Terraform to create the access policy you have to specify the Object ID of this Principal. This Object ID can be retrieved via following data reference, since it is different in every AAD Tenant:
Expand Down Expand Up @@ -77,6 +79,14 @@ The following attributes are exported:

* `thumbprint` - The thumbprint for the certificate.

---

A `hosting_environment` block supports the following:

* `resource_group_name` - The name of the resource group containing the App Service Environment (ASE).

* `hosting_environment` - The name of the App Service Environment (ASE).

## Timeouts

The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions:
Expand Down