Skip to content

Commit

Permalink
Add security center setting resource
Browse files Browse the repository at this point in the history
So that we can disable and/or enabled the access of Microsoft
App Security (MCAS) and Windows Defender ATP (WDATP) to the subscription
data.
  • Loading branch information
beandrad committed Oct 8, 2020
1 parent f6568c9 commit 9b4239b
Show file tree
Hide file tree
Showing 10 changed files with 399 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package azuresdkhacks

import (
"context"
"fmt"
"net/http"

"github.com/Azure/azure-sdk-for-go/services/preview/security/mgmt/v3.0/security"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
)

func GetSecurityCenterSetting(client *security.SettingsClient, ctx context.Context, settingName string) (setting security.DataExportSettings, err error) {
// NOTE: client.Get() returns security.Setting, which doesn't contain the "Enabled" property
req, err := client.GetPreparer(ctx, settingName)
if err != nil {
err = autorest.NewErrorWithError(err, "security.SettingsClient", "Get", nil, "Failure preparing request")
return setting, fmt.Errorf("Error reading Security Center setting: %+v", err)
}
resp, err := client.GetSender(req)
if err != nil {
err = autorest.NewErrorWithError(err, "security.SettingsClient", "Get", resp, "Failure sending request")
return setting, fmt.Errorf("Error reading Security Center setting: %+v", err)
}

err = autorest.Respond(
resp,
azure.WithErrorUnlessStatusCode(http.StatusOK),
autorest.ByUnmarshallingJSON(&setting),
autorest.ByClosing())
if err != nil {
return setting, fmt.Errorf("Error reading Security Center setting: %+v", err)
}

return setting, 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
SettingClient *security.SettingsClient
}

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

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

return &Client{
ContactsClient: &ContactsClient,
PricingClient: &PricingClient,
WorkspaceClient: &WorkspaceClient,
AdvancedThreatProtectionClient: &AdvancedThreatProtectionClient,
SettingClient: &SettingClient,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package parse

import (
"fmt"

"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
)

type SecurityCenterSettingId struct {
SettingName string
}

func SecurityCenterSettingID(input string) (*SecurityCenterSettingId, error) {
id, err := azure.ParseAzureResourceID(input)
if err != nil {
return nil, fmt.Errorf("Unable to parse Security Center Setting ID %q: %+v", input, err)
}

setting := SecurityCenterSettingId{}

if setting.SettingName, err = id.PopSegment("settings"); err != nil {
return nil, err
}

if err := id.ValidateNoEmptySegments(input); err != nil {
return nil, err
}

return &setting, nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package parse

import (
"testing"
)

func TestSecurityCenterSettingID(t *testing.T) {
testData := []struct {
Name string
Input string
Error bool
Expect *SecurityCenterSettingId
}{
{
Name: "Empty",
Input: "",
Error: true,
},
{
Name: "No Settings Segment",
Input: "/subscriptions/00000000-0000-0000-0000-000000000000",
Error: true,
},
{
Name: "No Settings Value",
Input: "/subscriptions/00000000-0000-0000-0000-000000000000/settings/",
Error: true,
},
{
Name: "Security Center Setting ID",
Input: "/subscriptions/00000000-0000-0000-0000-000000000000/settings/MCAS",
Expect: &SecurityCenterSettingId{
SettingName: "MCAS",
},
},
}

for _, v := range testData {
t.Logf("[DEBUG] Testing %q", v.Name)

actual, err := SecurityCenterSettingID(v.Input)
if err != nil {
if v.Error {
continue
}

t.Fatalf("Expected a value but got an error: %s", err)
}

if actual.SettingName != v.Expect.SettingName {
t.Fatalf("Expected %q but got %q for Name", v.Expect.SettingName, actual.SettingName)
}
}
}
1 change: 1 addition & 0 deletions azurerm/internal/services/securitycenter/registration.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ func (r Registration) SupportedResources() map[string]*schema.Resource {
return map[string]*schema.Resource{
"azurerm_advanced_threat_protection": resourceArmAdvancedThreatProtection(),
"azurerm_security_center_contact": resourceArmSecurityCenterContact(),
"azurerm_security_center_setting": resourceArmSecurityCenterSetting(),
"azurerm_security_center_subscription_pricing": resourceArmSecurityCenterSubscriptionPricing(),
"azurerm_security_center_workspace": resourceArmSecurityCenterWorkspace(),
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
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/services/securitycenter/azuresdkhacks"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/securitycenter/parse"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts"
)

func resourceArmSecurityCenterSetting() *schema.Resource {
return &schema.Resource{
Create: resourceArmSecurityCenterSettingUpdate,
Read: resourceArmSecurityCenterSettingRead,
Update: resourceArmSecurityCenterSettingUpdate,
Delete: resourceArmSecurityCenterSettingDelete,

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{
"setting_name": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{
"MCAS",
"WDATP",
}, false),
},
"enabled": {
Type: schema.TypeBool,
Required: true,
},
},
}
}

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

settingName := d.Get("setting_name").(string)
enabled := d.Get("enabled").(bool)
setting := security.DataExportSettings{
DataExportSettingProperties: &security.DataExportSettingProperties{
Enabled: &enabled,
},
Kind: security.KindDataExportSettings,
}

if _, err := client.Update(ctx, settingName, setting); err != nil {
return fmt.Errorf("Error creating/updating Security Center pricing: %+v", err)
}

resp, err := azuresdkhacks.GetSecurityCenterSetting(client, ctx, settingName)
if err != nil {
return fmt.Errorf("Error reading Security Center setting: %+v", err)
}

d.SetId(*resp.ID)

return resourceArmSecurityCenterSettingRead(d, meta)
}

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

id, err := parse.SecurityCenterSettingID(d.Id())
if err != nil {
return err
}
resp, err := azuresdkhacks.GetSecurityCenterSetting(client, ctx, id.SettingName)
if err != nil {
return fmt.Errorf("Error reading Security Center setting: %+v", err)
}

if err != nil {
return fmt.Errorf("Error reading Security Center setting: %+v", err)
}

if properties := resp.DataExportSettingProperties; properties != nil {
d.Set("enabled", properties.Enabled)
}
d.Set("setting_name", id.SettingName)

return nil
}

func resourceArmSecurityCenterSettingDelete(_ *schema.ResourceData, _ interface{}) error {
log.Printf("[DEBUG] Security Center deletion invocation")
return nil // cannot be deleted.
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package tests

import (
"fmt"
"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 TestAccAzureRMSecurityCenterSetting_update(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_security_center_setting", "test")

// lintignore:AT001
resource.Test(t, resource.TestCase{
PreCheck: func() { acceptance.PreCheck(t) },
Providers: acceptance.SupportedProviders,
Steps: []resource.TestStep{
{
Config: testAccAzureRMSecurityCenterSetting_cfg("MCAS", true),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMSecurityCenterSettingExists(data.ResourceName),
resource.TestCheckResourceAttr(data.ResourceName, "setting_name", "MCAS"),
resource.TestCheckResourceAttr(data.ResourceName, "enabled", "true"),
),
},
data.ImportStep(),
{
Config: testAccAzureRMSecurityCenterSetting_cfg("MCAS", false),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMSecurityCenterSettingExists(data.ResourceName),
resource.TestCheckResourceAttr(data.ResourceName, "setting_name", "MCAS"),
resource.TestCheckResourceAttr(data.ResourceName, "enabled", "false"),
),
},
data.ImportStep(),
{
Config: testAccAzureRMSecurityCenterSetting_cfg("WDATP", true),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMSecurityCenterSettingExists(data.ResourceName),
resource.TestCheckResourceAttr(data.ResourceName, "setting_name", "WDATP"),
resource.TestCheckResourceAttr(data.ResourceName, "enabled", "true"),
),
},
data.ImportStep(),
{
Config: testAccAzureRMSecurityCenterSetting_cfg("WDATP", false),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMSecurityCenterSettingExists(data.ResourceName),
resource.TestCheckResourceAttr(data.ResourceName, "setting_name", "WDATP"),
resource.TestCheckResourceAttr(data.ResourceName, "enabled", "false"),
),
},
data.ImportStep(),
},
})
}

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

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

settingName := rs.Primary.Attributes["setting_name"]

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

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

return nil
}
}

func testAccAzureRMSecurityCenterSetting_cfg(settingName string, enabled bool) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}
resource "azurerm_security_center_setting" "example" {
setting_name = "%s"
enabled = "%t"
}
`, settingName, enabled)
}
8 changes: 8 additions & 0 deletions examples/security/securitycenter-setting/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
provider "azurerm" {
features {}
}

resource "azurerm_security_center_setting" "example" {
setting_name = "MCAS"
enabled = true
}
4 changes: 4 additions & 0 deletions website/azurerm.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2626,6 +2626,10 @@
<a href="/docs/providers/azurerm/r/security_center_contact.html">azurerm_security_center_contact</a>
</li>

<li>
<a href="/docs/providers/azurerm/r/security_center_setting.html">azurerm_security_center_setting</a>
</li>

<li>
<a href="/docs/providers/azurerm/r/security_center_subscription_pricing.html">azurerm_security_center_subscription_pricing</a>
</li>
Expand Down

0 comments on commit 9b4239b

Please sign in to comment.