From 384520ba27ce15423ebbd98b2e4cacf4d1b5a8e2 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Thu, 28 Mar 2019 21:21:04 +0100 Subject: [PATCH 1/3] ew Resource: `azurerm_api_management_certificate` --- azurerm/config.go | 5 + azurerm/provider.go | 1 + ...resource_arm_api_management_certificate.go | 170 ++++++++++++++++++ ...rce_arm_api_management_certificate_test.go | 168 +++++++++++++++++ website/azurerm.erb | 4 + .../api_management_certificate.html.markdown | 76 ++++++++ 6 files changed, 424 insertions(+) create mode 100644 azurerm/resource_arm_api_management_certificate.go create mode 100644 azurerm/resource_arm_api_management_certificate_test.go create mode 100644 website/docs/r/api_management_certificate.html.markdown diff --git a/azurerm/config.go b/azurerm/config.go index 7290835938eb..cf9917a02e9e 100644 --- a/azurerm/config.go +++ b/azurerm/config.go @@ -129,6 +129,7 @@ type ArmClient struct { // API Management apiManagementApiClient apimanagement.APIClient apiManagementApiOperationsClient apimanagement.APIOperationClient + apiManagementCertificatesClient apimanagement.CertificateClient apiManagementGroupClient apimanagement.GroupClient apiManagementGroupUsersClient apimanagement.GroupUserClient apiManagementLoggerClient apimanagement.LoggerClient @@ -507,6 +508,10 @@ func (c *ArmClient) registerApiManagementServiceClients(endpoint, subscriptionId c.configureClient(&apiOperationsClient.Client, auth) c.apiManagementApiOperationsClient = apiOperationsClient + certificatesClient := apimanagement.NewCertificateClientWithBaseURI(endpoint, subscriptionId) + c.configureClient(&certificatesClient.Client, auth) + c.apiManagementCertificatesClient = certificatesClient + groupsClient := apimanagement.NewGroupClientWithBaseURI(endpoint, subscriptionId) c.configureClient(&groupsClient.Client, auth) c.apiManagementGroupClient = groupsClient diff --git a/azurerm/provider.go b/azurerm/provider.go index 3fabae6b9f04..a62cb1f047a6 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -171,6 +171,7 @@ func Provider() terraform.ResourceProvider { "azurerm_api_management": resourceArmApiManagementService(), "azurerm_api_management_api": resourceArmApiManagementApi(), "azurerm_api_management_api_operation": resourceArmApiManagementApiOperation(), + "azurerm_api_management_certificate": resourceArmApiManagementCertificate(), "azurerm_api_management_group": resourceArmApiManagementGroup(), "azurerm_api_management_group_user": resourceArmApiManagementGroupUser(), "azurerm_api_management_logger": resourceArmApiManagementLogger(), diff --git a/azurerm/resource_arm_api_management_certificate.go b/azurerm/resource_arm_api_management_certificate.go new file mode 100644 index 000000000000..508d76cd6cc8 --- /dev/null +++ b/azurerm/resource_arm_api_management_certificate.go @@ -0,0 +1,170 @@ +package azurerm + +import ( + "fmt" + "log" + "time" + + "github.com/Azure/azure-sdk-for-go/services/apimanagement/mgmt/2018-01-01/apimanagement" + "github.com/hashicorp/terraform/helper/schema" + "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/utils" +) + +func resourceArmApiManagementCertificate() *schema.Resource { + return &schema.Resource{ + Create: resourceArmApiManagementCertificateCreateUpdate, + Read: resourceArmApiManagementCertificateRead, + Update: resourceArmApiManagementCertificateCreateUpdate, + Delete: resourceArmApiManagementCertificateDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "name": azure.SchemaApiManagementChildName(), + + "resource_group_name": resourceGroupNameSchema(), + + "api_management_name": azure.SchemaApiManagementName(), + + "data": { + Type: schema.TypeString, + Required: true, + Sensitive: true, + ValidateFunc: validate.Base64String(), + }, + + "password": { + Type: schema.TypeString, + Optional: true, + Sensitive: true, + }, + + "expiration": { + Type: schema.TypeString, + Computed: true, + }, + + "subject": { + Type: schema.TypeString, + Computed: true, + }, + + "thumbprint": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func resourceArmApiManagementCertificateCreateUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).apiManagementCertificatesClient + ctx := meta.(*ArmClient).StopContext + + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + serviceName := d.Get("api_management_name").(string) + + data := d.Get("data").(string) + password := d.Get("password").(string) + if requireResourcesToBeImported { + existing, err := client.Get(ctx, resourceGroup, serviceName, name) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("Error checking for presence of existing Certificate %q (API Management Service %q / Resource Group %q): %s", name, serviceName, resourceGroup, err) + } + } + + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_api_management_certificate", *existing.ID) + } + } + + parameters := apimanagement.CertificateCreateOrUpdateParameters{ + CertificateCreateOrUpdateProperties: &apimanagement.CertificateCreateOrUpdateProperties{ + Data: utils.String(data), + Password: utils.String(password), + }, + } + + if _, err := client.CreateOrUpdate(ctx, resourceGroup, serviceName, name, parameters, ""); err != nil { + return fmt.Errorf("Error creating or updating Certificate %q (Resource Group %q / API Management Service %q): %+v", name, resourceGroup, serviceName, err) + } + + resp, err := client.Get(ctx, resourceGroup, serviceName, name) + if err != nil { + return fmt.Errorf("Error retrieving Certificate %q (Resource Group %q / API Management Service %q): %+v", name, resourceGroup, serviceName, err) + } + if resp.ID == nil { + return fmt.Errorf("Cannot read ID for Certificate %q (Resource Group %q / API Management Service %q)", name, resourceGroup, serviceName) + } + d.SetId(*resp.ID) + + return resourceArmApiManagementCertificateRead(d, meta) +} + +func resourceArmApiManagementCertificateRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).apiManagementCertificatesClient + ctx := meta.(*ArmClient).StopContext + + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + serviceName := id.Path["service"] + name := id.Path["certificates"] + + resp, err := client.Get(ctx, resourceGroup, serviceName, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + log.Printf("[DEBUG] Certificate %q (Resource Group %q / API Management Service %q) was not found - removing from state!", name, resourceGroup, serviceName) + d.SetId("") + return nil + } + + return fmt.Errorf("Error making Read request for Certificate %q (Resource Group %q / API Management Service %q): %+v", name, resourceGroup, serviceName, err) + } + + d.Set("name", resp.Name) + d.Set("resource_group_name", resourceGroup) + d.Set("api_management_name", serviceName) + + if props := resp.CertificateContractProperties; props != nil { + + if expiration := props.ExpirationDate; expiration != nil { + formatted := expiration.Format(time.RFC3339) + d.Set("expiration", formatted) + } + + d.Set("subject", props.Thumbprint) + d.Set("thumbprint", props.Thumbprint) + } + + return nil +} + +func resourceArmApiManagementCertificateDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).apiManagementCertificatesClient + ctx := meta.(*ArmClient).StopContext + + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + serviceName := id.Path["service"] + name := id.Path["certificates"] + + if resp, err := client.Delete(ctx, resourceGroup, serviceName, name, ""); err != nil { + if !utils.ResponseWasNotFound(resp) { + return fmt.Errorf("Error deleting Certificate %q (Resource Group %q / API Management Service %q): %+v", name, resourceGroup, serviceName, err) + } + } + + return nil +} diff --git a/azurerm/resource_arm_api_management_certificate_test.go b/azurerm/resource_arm_api_management_certificate_test.go new file mode 100644 index 000000000000..8fce6b0a6f11 --- /dev/null +++ b/azurerm/resource_arm_api_management_certificate_test.go @@ -0,0 +1,168 @@ +package azurerm + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func TestAccAzureRMAPIManagementCertificate_basic(t *testing.T) { + resourceName := "azurerm_api_management_certificate.test" + ri := tf.AccRandTimeInt() + location := testLocation() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMAPIManagementCertificateDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAPIManagementCertificate_basic(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAPIManagementCertificateExists(resourceName), + resource.TestCheckResourceAttrSet(resourceName, "expiration"), + resource.TestCheckResourceAttrSet(resourceName, "subject"), + resource.TestCheckResourceAttrSet(resourceName, "thumbprint"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + // not returned from the API + "data", + "password", + }, + }, + }, + }) +} + +func TestAccAzureRMAPIManagementCertificate_requiresImport(t *testing.T) { + if !requireResourcesToBeImported { + t.Skip("Skipping since resources aren't required to be imported") + return + } + + resourceName := "azurerm_api_management_certificate.test" + ri := tf.AccRandTimeInt() + location := testLocation() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMAPIManagementCertificateDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAPIManagementCertificate_basic(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAPIManagementCertificateExists(resourceName), + ), + }, + { + Config: testAccAzureRMAPIManagementCertificate_requiresImport(ri, location), + ExpectError: testRequiresImportError("azurerm_api_management_certificate"), + }, + }, + }) +} + +func testCheckAzureRMAPIManagementCertificateDestroy(s *terraform.State) error { + client := testAccProvider.Meta().(*ArmClient).apiManagementCertificatesClient + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_api_management_certificate" { + continue + } + + name := rs.Primary.Attributes["name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + serviceName := rs.Primary.Attributes["api_management_name"] + + ctx := testAccProvider.Meta().(*ArmClient).StopContext + resp, err := client.Get(ctx, resourceGroup, serviceName, name) + + if err != nil { + if !utils.ResponseWasNotFound(resp.Response) { + return err + } + } + + return nil + } + return nil +} + +func testCheckAzureRMAPIManagementCertificateExists(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("Not found: %s", resourceName) + } + + name := rs.Primary.Attributes["name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + serviceName := rs.Primary.Attributes["api_management_name"] + + client := testAccProvider.Meta().(*ArmClient).apiManagementCertificatesClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + resp, err := client.Get(ctx, resourceGroup, serviceName, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Bad: API Management Certificate %q (Resource Group %q / API Management Service %q) does not exist", name, resourceGroup, serviceName) + } + return fmt.Errorf("Bad: Get on apiManagementCertificatesClient: %+v", err) + } + + return nil + } +} + +func testAccAzureRMAPIManagementCertificate_basic(rInt int, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_api_management" "test" { + name = "acctestAM-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + publisher_name = "pub1" + publisher_email = "pub1@email.com" + + sku { + name = "Developer" + capacity = 1 + } +} + +resource "azurerm_api_management_certificate" "test" { + name = "example-cert" + api_management_name = "${azurerm_api_management.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" + data = "${base64encode(file("testdata/keyvaultcert.pfx"))}" + password = "" +} +`, rInt, location, rInt) +} + +func testAccAzureRMAPIManagementCertificate_requiresImport(rInt int, location string) string { + template := testAccAzureRMAPIManagementCertificate_basic(rInt, location) + return fmt.Sprintf(` +%s + +resource "azurerm_api_management_certificate" "import" { + name = "${azurerm_api_management_certificate.test.name}" + api_management_name = "${azurerm_api_management_certificate.test.api_management_name}" + resource_group_name = "${azurerm_api_management_certificate.test.resource_group_name}" + data = "${azurerm_api_management_certificate.test.data}" + password = "${azurerm_api_management_certificate.test.password}" +} +`, template) +} diff --git a/website/azurerm.erb b/website/azurerm.erb index 8bcdf81e52d2..b8942d84ebb6 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -346,6 +346,10 @@ azurerm_api_management_api_operation + > + azurerm_api_management_certificate + + > azurerm_api_management_group diff --git a/website/docs/r/api_management_certificate.html.markdown b/website/docs/r/api_management_certificate.html.markdown new file mode 100644 index 000000000000..04f7ff1bc475 --- /dev/null +++ b/website/docs/r/api_management_certificate.html.markdown @@ -0,0 +1,76 @@ +--- +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_api_management_certificate" +sidebar_current: "docs-azurerm-resource-api-management-certificate" +description: |- + Manages an Certificate within an API Management Service. +--- + +# azurerm_api_management_certificate + +Manages an Certificate within an API Management Service. + +## Example Usage + +```hcl +resource "azurerm_resource_group" "test" { + name = "example-resources" + location = "West Europe" +} + +resource "azurerm_api_management" "test" { + name = "example-apim" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + publisher_name = "My Company" + publisher_email = "company@terraform.io" + + sku { + name = "Developer" + capacity = 1 + } +} + +resource "azurerm_api_management_certificate" "test" { + name = "example-cert" + api_management_name = "${azurerm_api_management.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" + data = "${base64encode(file("example.pfx"))}" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name of the API Management Certificate. Changing this forces a new resource to be created. + +* `api_management_name` - (Required) The Name of the API Management Service where this Service should be created. Changing this forces a new resource to be created. + +* `resource_group_name` - (Required) The Name of the Resource Group where the API Management Service exists. Changing this forces a new resource to be created. + +* `data` - (Required) The base-64 encoded certificate data, which must be a PFX file. Changing this forces a new resource to be created. + +* `password` - (Optional) The password used for this certificate. Changing this forces a new resource to be created. + +--- + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - The ID of the API Management Certificate. + +* `expiration` - The Expiration Date of this Certificate, formatted as an RFC3339 string. + +* `subject` - The Subject of this Certificate. + +* `thumbprint` - The Thumbprint of this Certificate. + +## Import + +API Management Certificates can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_api_management_certificate.test /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/Microsoft.ApiManagement/service/instance1/certificates/certificate1 +``` From 49b84f0dca47fd45aeeffd604749da3139f447b3 Mon Sep 17 00:00:00 2001 From: kt Date: Fri, 29 Mar 2019 07:14:38 +0100 Subject: [PATCH 2/3] Update azurerm/resource_arm_api_management_certificate.go Co-Authored-By: tombuildsstuff --- azurerm/resource_arm_api_management_certificate.go | 1 + 1 file changed, 1 insertion(+) diff --git a/azurerm/resource_arm_api_management_certificate.go b/azurerm/resource_arm_api_management_certificate.go index 508d76cd6cc8..045778f03ec6 100644 --- a/azurerm/resource_arm_api_management_certificate.go +++ b/azurerm/resource_arm_api_management_certificate.go @@ -71,6 +71,7 @@ func resourceArmApiManagementCertificateCreateUpdate(d *schema.ResourceData, met data := d.Get("data").(string) password := d.Get("password").(string) + if requireResourcesToBeImported { existing, err := client.Get(ctx, resourceGroup, serviceName, name) if err != nil { From 60762d6ff39c6318a7ce341bddddf58033fd425d Mon Sep 17 00:00:00 2001 From: kt Date: Fri, 29 Mar 2019 07:14:45 +0100 Subject: [PATCH 3/3] Update azurerm/resource_arm_api_management_certificate.go Co-Authored-By: tombuildsstuff --- azurerm/resource_arm_api_management_certificate.go | 1 - 1 file changed, 1 deletion(-) diff --git a/azurerm/resource_arm_api_management_certificate.go b/azurerm/resource_arm_api_management_certificate.go index 045778f03ec6..53a3db4a724c 100644 --- a/azurerm/resource_arm_api_management_certificate.go +++ b/azurerm/resource_arm_api_management_certificate.go @@ -68,7 +68,6 @@ func resourceArmApiManagementCertificateCreateUpdate(d *schema.ResourceData, met name := d.Get("name").(string) resourceGroup := d.Get("resource_group_name").(string) serviceName := d.Get("api_management_name").(string) - data := d.Get("data").(string) password := d.Get("password").(string)