diff --git a/azurerm/config.go b/azurerm/config.go index 990d9978a285..f4414a901a14 100644 --- a/azurerm/config.go +++ b/azurerm/config.go @@ -258,7 +258,8 @@ type ArmClient struct { searchServicesClient search.ServicesClient // Security Centre - securityCenterPricingClient security.PricingsClient + securityCenterPricingClient security.PricingsClient + securityCenterContactsClient security.ContactsClient // ServiceBus serviceBusQueuesClient servicebus.QueuesClient @@ -1035,6 +1036,10 @@ func (c *ArmClient) registerSecurityCenterClients(endpoint, subscriptionId, ascL securityCenterPricingClient := security.NewPricingsClientWithBaseURI(endpoint, subscriptionId, ascLocation) c.configureClient(&securityCenterPricingClient.Client, auth) c.securityCenterPricingClient = securityCenterPricingClient + + securityCenterContactsClient := security.NewContactsClientWithBaseURI(endpoint, subscriptionId, ascLocation) + c.configureClient(&securityCenterContactsClient.Client, auth) + c.securityCenterContactsClient = securityCenterContactsClient } func (c *ArmClient) registerServiceBusClients(endpoint, subscriptionId string, auth autorest.Authorizer) { diff --git a/azurerm/provider.go b/azurerm/provider.go index 6e138cb467a6..ee79e9ec22ea 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -247,6 +247,7 @@ func Provider() terraform.ResourceProvider { "azurerm_route_table": resourceArmRouteTable(), "azurerm_search_service": resourceArmSearchService(), "azurerm_security_center_subscription_pricing": resourceArmSecurityCenterSubscriptionPricing(), + "azurerm_security_center_contact": resourceArmSecurityCenterContact(), "azurerm_servicebus_namespace": resourceArmServiceBusNamespace(), "azurerm_servicebus_namespace_authorization_rule": resourceArmServiceBusNamespaceAuthorizationRule(), "azurerm_servicebus_queue": resourceArmServiceBusQueue(), diff --git a/azurerm/resource_arm_security_center_contact.go b/azurerm/resource_arm_security_center_contact.go new file mode 100644 index 000000000000..6d1d24529d01 --- /dev/null +++ b/azurerm/resource_arm_security_center_contact.go @@ -0,0 +1,149 @@ +package azurerm + +import ( + "fmt" + "github.com/Azure/azure-sdk-for-go/services/preview/security/mgmt/2017-08-01-preview/security" + "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/terraform/helper/validation" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" + "log" +) + +//seems you can only set one contact: +// Invalid security contact name was provided - only 'defaultX' is allowed where X is an index +// Invalid security contact name 'default0' was provided. Expected 'default1' +// Message="Invalid security contact name 'default2' was provided. Expected 'default1'" +const securityCenterContactName = "default1" + +func resourceArmSecurityCenterContact() *schema.Resource { + return &schema.Resource{ + Create: resourceArmSecurityCenterContactCreateUpdate, + Read: resourceArmSecurityCenterContactRead, + Update: resourceArmSecurityCenterContactCreateUpdate, + Delete: resourceArmSecurityCenterContactDelete, + + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "email": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.NoZeroValues, + }, + + "phone": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.NoZeroValues, + }, + + "alert_notifications": { + Type: schema.TypeBool, + Required: true, + }, + + "alerts_to_admins": { + Type: schema.TypeBool, + Required: true, + }, + }, + } +} + +func resourceArmSecurityCenterContactCreateUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).securityCenterContactsClient + ctx := meta.(*ArmClient).StopContext + + name := securityCenterContactName + + contact := security.Contact{ + ContactProperties: &security.ContactProperties{ + Email: utils.String(d.Get("email").(string)), + Phone: utils.String(d.Get("phone").(string)), + }, + } + + if alertNotifications := d.Get("alert_notifications").(bool); alertNotifications { + contact.AlertNotifications = security.On + } else { + contact.AlertNotifications = security.Off + } + + if alertNotifications := d.Get("alerts_to_admins").(bool); alertNotifications { + contact.AlertsToAdmins = security.AlertsToAdminsOn + } else { + contact.AlertsToAdmins = security.AlertsToAdminsOff + } + + if d.IsNewResource() { + _, err := client.Create(ctx, name, contact) + if err != nil { + return fmt.Errorf("Error creating Security Center Contact: %+v", err) + } + + resp, err := client.Get(ctx, name) + if err != nil { + return fmt.Errorf("Error reading Security Center Contact: %+v", err) + } + if resp.ID == nil { + return fmt.Errorf("Security Center Contact ID is nil") + } + + d.SetId(*resp.ID) + } else { + _, err := client.Update(ctx, name, contact) + if err != nil { + return fmt.Errorf("Error updating Security Center Contact: %+v", err) + } + } + + return resourceArmSecurityCenterContactRead(d, meta) +} + +func resourceArmSecurityCenterContactRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).securityCenterContactsClient + ctx := meta.(*ArmClient).StopContext + + name := securityCenterContactName + + resp, err := client.Get(ctx, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + log.Printf("[DEBUG] Security Center Subscription Contact was not found: %v", err) + d.SetId("") + return nil + } + + return fmt.Errorf("Error reading Security Center Contact: %+v", err) + } + + if properties := resp.ContactProperties; properties != nil { + d.Set("email", properties.Email) + d.Set("phone", properties.Phone) + d.Set("alert_notifications", properties.AlertNotifications == security.On) + d.Set("alerts_to_admins", properties.AlertsToAdmins == security.AlertsToAdminsOn) + } + + return nil +} + +func resourceArmSecurityCenterContactDelete(_ *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).securityCenterContactsClient + ctx := meta.(*ArmClient).StopContext + + name := securityCenterContactName + + resp, err := client.Delete(ctx, name) + if err != nil { + if utils.ResponseWasNotFound(resp) { + log.Printf("[DEBUG] Security Center Subscription Contact was not found: %v", err) + return nil + } + + return fmt.Errorf("Error deleting Security Center Contact: %+v", err) + } + + return nil +} diff --git a/azurerm/resource_arm_security_center_contact_test.go b/azurerm/resource_arm_security_center_contact_test.go new file mode 100644 index 000000000000..3a8e2857203f --- /dev/null +++ b/azurerm/resource_arm_security_center_contact_test.go @@ -0,0 +1,130 @@ +package azurerm + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func TestAccAzureRMSecurityCenterContact_basic(t *testing.T) { + resourceName := "azurerm_security_center_contact.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMSecurityCenterContactDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMSecurityCenterContact_template("email1@example.com", "+1-555-555-5555", true, true), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMSecurityCenterContactExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "email", "email1@example.com"), + resource.TestCheckResourceAttr(resourceName, "phone", "+1-555-555-5555"), + resource.TestCheckResourceAttr(resourceName, "alert_notifications", "true"), + resource.TestCheckResourceAttr(resourceName, "alerts_to_admins", "true"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAzureRMSecurityCenterContact_update(t *testing.T) { + resourceName := "azurerm_security_center_contact.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMSecurityCenterContactDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMSecurityCenterContact_template("email1@example.com", "+1-555-555-5555", true, true), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMSecurityCenterContactExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "email", "email1@example.com"), + resource.TestCheckResourceAttr(resourceName, "phone", "+1-555-555-5555"), + resource.TestCheckResourceAttr(resourceName, "alert_notifications", "true"), + resource.TestCheckResourceAttr(resourceName, "alerts_to_admins", "true"), + ), + }, + { + Config: testAccAzureRMSecurityCenterContact_template("email2@example.com", "+1-555-678-6789", false, false), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMSecurityCenterContactExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "email", "email2@example.com"), + resource.TestCheckResourceAttr(resourceName, "phone", "+1-555-678-6789"), + resource.TestCheckResourceAttr(resourceName, "alert_notifications", "false"), + resource.TestCheckResourceAttr(resourceName, "alerts_to_admins", "false"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testCheckAzureRMSecurityCenterContactExists(name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + client := testAccProvider.Meta().(*ArmClient).securityCenterContactsClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + + rs, ok := s.RootModule().Resources[name] + if !ok { + return fmt.Errorf("Not found: %s", name) + } + + contactName := rs.Primary.Attributes["securityContacts"] + + resp, err := client.Get(ctx, contactName) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Security Center Subscription Contact %q was not found: %+v", contactName, err) + } + + return fmt.Errorf("Bad: GetContact: %+v", err) + } + + return nil + } +} + +func testCheckAzureRMSecurityCenterContactDestroy(s *terraform.State) error { + client := testAccProvider.Meta().(*ArmClient).securityCenterContactsClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + for _, res := range s.RootModule().Resources { + if res.Type != "azurerm_security_center_contact" { + continue + } + resp, err := client.Get(ctx, securityCenterContactName) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return nil + } + return err + } + return fmt.Errorf("security center contact still exists") + } + return nil +} + +func testAccAzureRMSecurityCenterContact_template(email, phone string, notifications, adminAlerts bool) string { + return fmt.Sprintf(` +resource "azurerm_security_center_contact" "test" { + email = "%s" + phone = "%s" + + alert_notifications = %t + alerts_to_admins = %t +} +`, email, phone, notifications, adminAlerts) +} diff --git a/website/azurerm.erb b/website/azurerm.erb index 08fe18acd2b9..32afed36b18a 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -987,6 +987,11 @@