Skip to content

Commit

Permalink
Merge pull request #2072 from terraform-providers/r-security-workspace
Browse files Browse the repository at this point in the history
New Resource: azurerm_securitycenter_workspace
  • Loading branch information
katbyte authored Oct 14, 2018
2 parents 5723395 + 8d17f21 commit ca6c3a1
Show file tree
Hide file tree
Showing 10 changed files with 447 additions and 4 deletions.
9 changes: 7 additions & 2 deletions azurerm/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,8 +258,9 @@ type ArmClient struct {
searchServicesClient search.ServicesClient

// Security Centre
securityCenterPricingClient security.PricingsClient
securityCenterContactsClient security.ContactsClient
securityCenterPricingClient security.PricingsClient
securityCenterContactsClient security.ContactsClient
securityCenterWorkspaceClient security.WorkspaceSettingsClient

// ServiceBus
serviceBusQueuesClient servicebus.QueuesClient
Expand Down Expand Up @@ -1040,6 +1041,10 @@ func (c *ArmClient) registerSecurityCenterClients(endpoint, subscriptionId, ascL
securityCenterContactsClient := security.NewContactsClientWithBaseURI(endpoint, subscriptionId, ascLocation)
c.configureClient(&securityCenterContactsClient.Client, auth)
c.securityCenterContactsClient = securityCenterContactsClient

securityCenterWorkspaceClient := security.NewWorkspaceSettingsClientWithBaseURI(endpoint, subscriptionId, ascLocation)
c.configureClient(&securityCenterWorkspaceClient.Client, auth)
c.securityCenterWorkspaceClient = securityCenterWorkspaceClient
}

func (c *ArmClient) registerServiceBusClients(endpoint, subscriptionId string, auth autorest.Authorizer) {
Expand Down
1 change: 1 addition & 0 deletions azurerm/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ func Provider() terraform.ResourceProvider {
"azurerm_search_service": resourceArmSearchService(),
"azurerm_security_center_subscription_pricing": resourceArmSecurityCenterSubscriptionPricing(),
"azurerm_security_center_contact": resourceArmSecurityCenterContact(),
"azurerm_security_center_workspace": resourceArmSecurityCenterWorkspace(),
"azurerm_servicebus_namespace": resourceArmServiceBusNamespace(),
"azurerm_servicebus_namespace_authorization_rule": resourceArmServiceBusNamespaceAuthorizationRule(),
"azurerm_servicebus_queue": resourceArmServiceBusQueue(),
Expand Down
3 changes: 2 additions & 1 deletion azurerm/resource_arm_security_center_contact.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ package azurerm

import (
"fmt"
"log"

"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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

func TestAccAzureRMSecurityCenterSubscriptionPricing_update(t *testing.T) {
func testAccAzureRMSecurityCenterSubscriptionPricing_update(t *testing.T) {
resourceName := "azurerm_security_center_subscription_pricing.test"

resource.Test(t, resource.TestCase{
Expand Down
31 changes: 31 additions & 0 deletions azurerm/resource_arm_security_center_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package azurerm

import (
"testing"
)

func TestAccAzureRMSecurityCenter_pricingAndWorkspace(t *testing.T) {
// NOTE: this is a combined test rather than separate split out tests
// due to the workspace tests depending on the current pricing tier
testCases := map[string]map[string]func(t *testing.T){
"pricing": {
"update": testAccAzureRMSecurityCenterSubscriptionPricing_update,
},
"workspace": {
"basic": testAccAzureRMSecurityCenterWorkspace_basic,
"update": testAccAzureRMSecurityCenterWorkspace_update,
},
}

for group, m := range testCases {
m := m
t.Run(group, func(t *testing.T) {
for name, tc := range m {
tc := tc
t.Run(name, func(t *testing.T) {
tc(t)
})
}
})
}
}
161 changes: 161 additions & 0 deletions azurerm/resource_arm_security_center_workspace.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
package azurerm

import (
"fmt"
"log"
"time"

"github.com/Azure/azure-sdk-for-go/services/preview/security/mgmt/2017-08-01-preview/security"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

//only valid name is default
// Message="Invalid workspace settings name 'kttest' , only default is allowed "
const securityCenterWorkspaceName = "default"

func resourceArmSecurityCenterWorkspace() *schema.Resource {
return &schema.Resource{
Create: resourceArmSecurityCenterWorkspaceCreateUpdate,
Read: resourceArmSecurityCenterWorkspaceRead,
Update: resourceArmSecurityCenterWorkspaceCreateUpdate,
Delete: resourceArmSecurityCenterWorkspaceDelete,

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

Schema: map[string]*schema.Schema{
"scope": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.NoZeroValues,
},

"workspace_id": {
Type: schema.TypeString,
Required: true,
ValidateFunc: azure.ValidateResourceID,
},
},
}
}

func resourceArmSecurityCenterWorkspaceCreateUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient).securityCenterWorkspaceClient
ctx := meta.(*ArmClient).StopContext

priceClient := meta.(*ArmClient).securityCenterPricingClient

//get pricing tier, workspace can only be configured when tier is not Free.
//API does not error, it just doesn't set the workspace scope
price, err := priceClient.GetSubscriptionPricing(ctx, securityCenterSubscriptionPricingName)
if err != nil {
return fmt.Errorf("Error reading Security Center Subscription pricing: %+v", err)
}

if price.PricingProperties == nil {
return fmt.Errorf("Security Center Subscription pricing propertier is nil")
}
if price.PricingProperties.PricingTier == security.Free {
return fmt.Errorf("Security Center Subscription workspace cannot be set when pricing tier is `Free`")
}

name := securityCenterWorkspaceName

contact := security.WorkspaceSetting{
WorkspaceSettingProperties: &security.WorkspaceSettingProperties{
Scope: utils.String(d.Get("scope").(string)),
WorkspaceID: utils.String(d.Get("workspace_id").(string)),
},
}

if d.IsNewResource() {
_, err := client.Create(ctx, name, contact)
if err != nil {
return fmt.Errorf("Error creating Security Center Workspace: %+v", err)
}
} else {
_, err := client.Update(ctx, name, contact)
if err != nil {
return fmt.Errorf("Error updating Security Center Workspace: %+v", err)
}
}

//api returns "" for workspace id after an create/update and eventually the new value
stateConf := &resource.StateChangeConf{
Pending: []string{"Waiting"},
Target: []string{"Populated"},
Timeout: 15 * time.Minute,
MinTimeout: 30 * time.Second,
Refresh: func() (interface{}, string, error) {

resp, err := client.Get(ctx, name)
if err != nil {
return resp, "Error", fmt.Errorf("Error reading Security Center Workspace: %+v", err)
}

if properties := resp.WorkspaceSettingProperties; properties != nil {
if properties.WorkspaceID != nil && *properties.WorkspaceID != "" {
return resp, "Populated", nil
}
}

return resp, "Waiting", nil
},
}

resp, err := stateConf.WaitForState()
if err != nil {
return fmt.Errorf("Error waiting: %+v", err)
}

if d.IsNewResource() {
d.SetId(*resp.(security.WorkspaceSetting).ID)
}

return resourceArmSecurityCenterWorkspaceRead(d, meta)
}

func resourceArmSecurityCenterWorkspaceRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient).securityCenterWorkspaceClient
ctx := meta.(*ArmClient).StopContext

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

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

if properties := resp.WorkspaceSettingProperties; properties != nil {
d.Set("scope", properties.Scope)
d.Set("workspace_id", properties.WorkspaceID)
}

return nil
}

func resourceArmSecurityCenterWorkspaceDelete(_ *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient).securityCenterWorkspaceClient
ctx := meta.(*ArmClient).StopContext

resp, err := client.Delete(ctx, securityCenterWorkspaceName)
if err != nil {
if utils.ResponseWasNotFound(resp) {
log.Printf("[DEBUG] Security Center Subscription Workspace was not found: %v", err)
return nil
}

return fmt.Errorf("Error deleting Security Center Workspace: %+v", err)
}

return nil
}
Loading

0 comments on commit ca6c3a1

Please sign in to comment.