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

Adds new resource for azurerm_security_center_auto_provisioning #8595

Merged
merged 9 commits into from
Oct 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package securitycenter

import (
"fmt"
"log"
"time"

"github.com/Azure/azure-sdk-for-go/services/preview/security/mgmt/v3.0/security"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

// NOTE: 'default' is the only valid name currently supported by the API
// No other names can be created and the 'default' resource can not be destroyed
const securityCenterAutoProvisioningName = "default"

func resourceArmSecurityCenterAutoProvisioning() *schema.Resource {
return &schema.Resource{
Create: resourceArmSecurityCenterAutoProvisioningUpdate,
Read: resourceArmSecurityCenterAutoProvisioningRead,
Update: resourceArmSecurityCenterAutoProvisioningUpdate,
Delete: resourceArmSecurityCenterAutoProvisioningDelete,

Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(60 * time.Minute),
Read: schema.DefaultTimeout(5 * time.Minute),
Update: schema.DefaultTimeout(60 * time.Minute),
Delete: schema.DefaultTimeout(60 * time.Minute),
},

Schema: map[string]*schema.Schema{
"auto_provision": {
Type: schema.TypeString,
Required: true,
// NOTE: the API seems case insensitive to this string value, 'ON', 'On', 'on' all work
ValidateFunc: validation.StringInSlice([]string{
string(security.AutoProvisionOn),
string(security.AutoProvisionOff),
}, false),
},
},
}
}

func resourceArmSecurityCenterAutoProvisioningUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).SecurityCenter.AutoProvisioningClient
ctx, cancel := timeouts.ForUpdate(meta.(*clients.Client).StopContext, d)
defer cancel()

// No need for import check as there's always single resource called 'default'
// - it cannot be deleted, all this does is set a string property to: "on" or "off"

// Build settings struct with auto_provision value
settings := security.AutoProvisioningSetting{
AutoProvisioningSettingProperties: &security.AutoProvisioningSettingProperties{
AutoProvision: security.AutoProvision(d.Get("auto_provision").(string)),
},
}

// There is no update function or operation in the API, only create
if _, err := client.Create(ctx, securityCenterAutoProvisioningName, settings); err != nil {
return fmt.Errorf("Error creating/updating Security Center auto provisioning: %+v", err)
}

resp, err := client.Get(ctx, securityCenterAutoProvisioningName)
if err != nil {
return fmt.Errorf("Error reading Security Center auto provisioning: %+v", err)
}
if resp.ID == nil || *resp.ID == "" {
return fmt.Errorf("Security Center auto provisioning ID is nil or empty")
}

d.SetId(*resp.ID)

return resourceArmSecurityCenterAutoProvisioningRead(d, meta)
}

func resourceArmSecurityCenterAutoProvisioningRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).SecurityCenter.AutoProvisioningClient
ctx, cancel := timeouts.ForUpdate(meta.(*clients.Client).StopContext, d)
defer cancel()

resp, err := client.Get(ctx, securityCenterAutoProvisioningName)
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
log.Printf("[DEBUG] Security Center subscription was not found: %v", err)
d.SetId("")
return nil
}

return fmt.Errorf("Error reading Security Center auto provisioning: %+v", err)
}

if properties := resp.AutoProvisioningSettingProperties; properties != nil {
d.Set("auto_provision", properties.AutoProvision)
}

return nil
}

func resourceArmSecurityCenterAutoProvisioningDelete(d *schema.ResourceData, meta interface{}) error {
// The API has no delete operation
// Instead we reset back to 'Off' which is the default

client := meta.(*clients.Client).SecurityCenter.AutoProvisioningClient
ctx, cancel := timeouts.ForUpdate(meta.(*clients.Client).StopContext, d)
defer cancel()

settings := security.AutoProvisioningSetting{
AutoProvisioningSettingProperties: &security.AutoProvisioningSettingProperties{
AutoProvision: "Off",
},
}

// There is no update function or operation in the API, only create
if _, err := client.Create(ctx, securityCenterAutoProvisioningName, settings); err != nil {
return fmt.Errorf("Error resetting Security Center auto provisioning to 'Off': %+v", err)
}

return nil
}
5 changes: 5 additions & 0 deletions azurerm/internal/services/securitycenter/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ type Client struct {
PricingClient *security.PricingsClient
WorkspaceClient *security.WorkspaceSettingsClient
AdvancedThreatProtectionClient *security.AdvancedThreatProtectionClient
AutoProvisioningClient *security.AutoProvisioningSettingsClient
SettingClient *security.SettingsClient
}

Expand All @@ -28,6 +29,9 @@ func NewClient(o *common.ClientOptions) *Client {
AdvancedThreatProtectionClient := security.NewAdvancedThreatProtectionClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId, ascLocation)
o.ConfigureClient(&AdvancedThreatProtectionClient.Client, o.ResourceManagerAuthorizer)

AutoProvisioningClient := security.NewAutoProvisioningSettingsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId, ascLocation)
o.ConfigureClient(&AutoProvisioningClient.Client, o.ResourceManagerAuthorizer)
benc-uk marked this conversation as resolved.
Show resolved Hide resolved

SettingClient := security.NewSettingsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId, ascLocation)
o.ConfigureClient(&SettingClient.Client, o.ResourceManagerAuthorizer)

Expand All @@ -36,6 +40,7 @@ func NewClient(o *common.ClientOptions) *Client {
PricingClient: &PricingClient,
WorkspaceClient: &WorkspaceClient,
AdvancedThreatProtectionClient: &AdvancedThreatProtectionClient,
AutoProvisioningClient: &AutoProvisioningClient,
SettingClient: &SettingClient,
}
}
1 change: 1 addition & 0 deletions azurerm/internal/services/securitycenter/registration.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,6 @@ func (r Registration) SupportedResources() map[string]*schema.Resource {
"azurerm_security_center_setting": resourceArmSecurityCenterSetting(),
"azurerm_security_center_subscription_pricing": resourceArmSecurityCenterSubscriptionPricing(),
"azurerm_security_center_workspace": resourceArmSecurityCenterWorkspace(),
"azurerm_security_center_auto_provisioning": resourceArmSecurityCenterAutoProvisioning(),
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package tests

import (
"fmt"
"strings"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/terraform"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

func TestAccAzureRMSecurityCenterAutoProvision_update(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_security_center_auto_provisioning", "test")

// lintignore:AT001
resource.Test(t, resource.TestCase{
PreCheck: func() { acceptance.PreCheck(t) },
Providers: acceptance.SupportedProviders,
Steps: []resource.TestStep{
{
Config: testAccAzureRMSecurityCenterAutoProvisioning_setting("On"),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMSecurityCenterAutoProvisioningExists(data.ResourceName, "On"),
resource.TestCheckResourceAttr(data.ResourceName, "auto_provision", "On"),
),
},
data.ImportStep(),
{
Config: testAccAzureRMSecurityCenterAutoProvisioning_setting("Off"),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMSecurityCenterAutoProvisioningExists(data.ResourceName, "Off"),
resource.TestCheckResourceAttr(data.ResourceName, "auto_provision", "Off"),
),
},
data.ImportStep(),
},
})
}

func testCheckAzureRMSecurityCenterAutoProvisioningExists(resourceName string, expectedSetting string) resource.TestCheckFunc {
return func(s *terraform.State) error {
client := acceptance.AzureProvider.Meta().(*clients.Client).SecurityCenter.AutoProvisioningClient
ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext

rs, ok := s.RootModule().Resources[resourceName]
if !ok {
return fmt.Errorf("Not found: %s", resourceName)
}

idSplit := strings.Split(rs.Primary.Attributes["id"], "/")
autoProvisionResourceName := idSplit[len(idSplit)-1]

resp, err := client.Get(ctx, autoProvisionResourceName)
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
return fmt.Errorf("Security Center auto provision %q was not found: %+v", autoProvisionResourceName, err)
}

return fmt.Errorf("Bad: GetAutoProvisioning: %+v", err)
}

// Check expected value
if string(resp.AutoProvision) != expectedSetting {
return fmt.Errorf("Security Center auto provision not expected, wanted %s, but got %s", expectedSetting, string(resp.AutoProvision))
}

return nil
}
}

func testAccAzureRMSecurityCenterAutoProvisioning_setting(setting string) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}

resource "azurerm_security_center_auto_provisioning" "test" {
auto_provision = "%s"
}
`, setting)
}