Skip to content

Commit

Permalink
Event Grid support for inbound ip filter (#9922)
Browse files Browse the repository at this point in the history
Co-authored-by: kt <kt@katbyte.me>

Fixes #9400
  • Loading branch information
jrauschenbusch committed Jan 8, 2021
1 parent 92f8602 commit 9387ef3
Show file tree
Hide file tree
Showing 7 changed files with 278 additions and 25 deletions.
95 changes: 95 additions & 0 deletions azurerm/internal/services/eventgrid/eventgrid.go
@@ -0,0 +1,95 @@
package eventgrid

import (
"github.com/Azure/azure-sdk-for-go/services/preview/eventgrid/mgmt/2020-04-01-preview/eventgrid"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

func eventSubscriptionPublicNetworkAccessEnabled() *schema.Schema {
return &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Default: true,
}
}

func eventSubscriptionInboundIPRule() *schema.Schema {
return &schema.Schema{
Type: schema.TypeList,
Optional: true,
MaxItems: 128,
ConfigMode: schema.SchemaConfigModeAttr,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"ip_mask": {
Type: schema.TypeString,
Required: true,
},
"action": {
Type: schema.TypeString,
Optional: true,
Default: string(eventgrid.Allow),
ValidateFunc: validation.StringInSlice([]string{
string(eventgrid.Allow),
}, false),
},
},
},
}
}

func expandPublicNetworkAccess(d *schema.ResourceData) eventgrid.PublicNetworkAccess {
if v, ok := d.GetOk("public_network_access_enabled"); ok {
enabled := eventgrid.Disabled
if v.(bool) {
enabled = eventgrid.Enabled
}
return enabled
}
return eventgrid.Disabled
}

func expandInboundIPRules(d *schema.ResourceData) *[]eventgrid.InboundIPRule {
inboundIPRuleList := d.Get("inbound_ip_rule").([]interface{})
if len(inboundIPRuleList) == 0 {
return nil
}

rules := make([]eventgrid.InboundIPRule, 0)

for _, r := range inboundIPRuleList {
rawRule := r.(map[string]interface{})
rule := &eventgrid.InboundIPRule{
Action: eventgrid.IPActionType(rawRule["action"].(string)),
IPMask: utils.String(rawRule["ip_mask"].(string)),
}

rules = append(rules, *rule)
}
return &rules
}

func flattenPublicNetworkAccess(in eventgrid.PublicNetworkAccess) bool {
return in == eventgrid.Enabled
}

func flattenInboundIPRules(in *[]eventgrid.InboundIPRule) []interface{} {
rules := make([]interface{}, 0)
if in == nil {
return rules
}

for _, r := range *in {
rawRule := make(map[string]interface{})

rawRule["action"] = string(r.Action)

if r.IPMask != nil {
rawRule["ip_mask"] = *r.IPMask
}
rules = append(rules, rawRule)
}
return rules
}
46 changes: 31 additions & 15 deletions azurerm/internal/services/eventgrid/eventgrid_domain_resource.go
Expand Up @@ -138,6 +138,10 @@ func resourceEventGridDomain() *schema.Resource {
},
},

"public_network_access_enabled": eventSubscriptionPublicNetworkAccessEnabled(),

"inbound_ip_rule": eventSubscriptionInboundIPRule(),

"endpoint": {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -170,7 +174,7 @@ func resourceEventGridDomainCreateUpdate(d *schema.ResourceData, meta interface{
existing, err := client.Get(ctx, resourceGroup, name)
if err != nil {
if !utils.ResponseWasNotFound(existing.Response) {
return fmt.Errorf("Error checking for presence of existing EventGrid Domain %q (Resource Group %q): %s", name, resourceGroup, err)
return fmt.Errorf("checking for presence of existing EventGrid Domain %q (Resource Group %q): %s", name, resourceGroup, err)
}
}

Expand All @@ -183,8 +187,10 @@ func resourceEventGridDomainCreateUpdate(d *schema.ResourceData, meta interface{
t := d.Get("tags").(map[string]interface{})

domainProperties := &eventgrid.DomainProperties{
InputSchemaMapping: expandAzureRmEventgridDomainInputMapping(d),
InputSchema: eventgrid.InputSchema(d.Get("input_schema").(string)),
InputSchemaMapping: expandAzureRmEventgridDomainInputMapping(d),
InputSchema: eventgrid.InputSchema(d.Get("input_schema").(string)),
PublicNetworkAccess: expandPublicNetworkAccess(d),
InboundIPRules: expandInboundIPRules(d),
}

domain := eventgrid.Domain{
Expand All @@ -197,19 +203,19 @@ func resourceEventGridDomainCreateUpdate(d *schema.ResourceData, meta interface{

future, err := client.CreateOrUpdate(ctx, resourceGroup, name, domain)
if err != nil {
return fmt.Errorf("Error creating/updating EventGrid Domain %q (Resource Group %q): %s", name, resourceGroup, err)
return fmt.Errorf("creating/updating EventGrid Domain %q (Resource Group %q): %s", name, resourceGroup, err)
}

if err = future.WaitForCompletionRef(ctx, client.Client); err != nil {
return fmt.Errorf("Error waiting for EventGrid Domain %q (Resource Group %q) to become available: %s", name, resourceGroup, err)
return fmt.Errorf("waiting for EventGrid Domain %q (Resource Group %q) to become available: %s", name, resourceGroup, err)
}

read, err := client.Get(ctx, resourceGroup, name)
if err != nil {
return fmt.Errorf("Error retrieving EventGrid Domain %q (Resource Group %q): %s", name, resourceGroup, err)
return fmt.Errorf("retrieving EventGrid Domain %q (Resource Group %q): %s", name, resourceGroup, err)
}
if read.ID == nil {
return fmt.Errorf("Cannot read EventGrid Domain %q (resource group %s) ID", name, resourceGroup)
return fmt.Errorf("reading EventGrid Domain %q (resource group %s) ID", name, resourceGroup)
}

d.SetId(*read.ID)
Expand All @@ -235,7 +241,7 @@ func resourceEventGridDomainRead(d *schema.ResourceData, meta interface{}) error
return nil
}

return fmt.Errorf("Error making Read request on EventGrid Domain %q: %+v", id.Name, err)
return fmt.Errorf("making Read request on EventGrid Domain %q: %+v", id.Name, err)
}

d.Set("name", resp.Name)
Expand All @@ -251,24 +257,34 @@ func resourceEventGridDomainRead(d *schema.ResourceData, meta interface{}) error

inputMappingFields, err := flattenAzureRmEventgridDomainInputMapping(props.InputSchemaMapping)
if err != nil {
return fmt.Errorf("Unable to flatten `input_schema_mapping_fields` for EventGrid Domain %q (Resource Group %q): %s", id.Name, id.ResourceGroup, err)
return fmt.Errorf("flattening `input_schema_mapping_fields` for EventGrid Domain %q (Resource Group %q): %s", id.Name, id.ResourceGroup, err)
}
if err := d.Set("input_mapping_fields", inputMappingFields); err != nil {
return fmt.Errorf("Error setting `input_schema_mapping_fields` for EventGrid Domain %q (Resource Group %q): %s", id.Name, id.ResourceGroup, err)
return fmt.Errorf("setting `input_schema_mapping_fields` for EventGrid Domain %q (Resource Group %q): %s", id.Name, id.ResourceGroup, err)
}

inputMappingDefaultValues, err := flattenAzureRmEventgridDomainInputMappingDefaultValues(props.InputSchemaMapping)
if err != nil {
return fmt.Errorf("Unable to flatten `input_schema_mapping_default_values` for EventGrid Domain %q (Resource Group %q): %s", id.Name, id.ResourceGroup, err)
return fmt.Errorf("flattening `input_schema_mapping_default_values` for EventGrid Domain %q (Resource Group %q): %s", id.Name, id.ResourceGroup, err)
}
if err := d.Set("input_mapping_default_values", inputMappingDefaultValues); err != nil {
return fmt.Errorf("Error setting `input_schema_mapping_fields` for EventGrid Domain %q (Resource Group %q): %s", id.Name, id.ResourceGroup, err)
return fmt.Errorf("setting `input_schema_mapping_fields` for EventGrid Domain %q (Resource Group %q): %s", id.Name, id.ResourceGroup, err)
}

publicNetworkAccessEnabled := flattenPublicNetworkAccess(props.PublicNetworkAccess)
if err := d.Set("public_network_access_enabled", publicNetworkAccessEnabled); err != nil {
return fmt.Errorf("setting `public_network_access_enabled` in EventGrid Domain %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err)
}

inboundIPRules := flattenInboundIPRules(props.InboundIPRules)
if err := d.Set("inbound_ip_rule", inboundIPRules); err != nil {
return fmt.Errorf("setting `inbound_ip_rule` in EventGrid Domain %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err)
}
}

keys, err := client.ListSharedAccessKeys(ctx, id.ResourceGroup, id.Name)
if err != nil {
return fmt.Errorf("Error retrieving Shared Access Keys for EventGrid Domain %q: %+v", id.Name, err)
return fmt.Errorf("retrieving Shared Access Keys for EventGrid Domain %q: %+v", id.Name, err)
}
d.Set("primary_access_key", keys.Key1)
d.Set("secondary_access_key", keys.Key2)
Expand All @@ -291,14 +307,14 @@ func resourceEventGridDomainDelete(d *schema.ResourceData, meta interface{}) err
if response.WasNotFound(future.Response()) {
return nil
}
return fmt.Errorf("Error deleting Event Grid Domain %q: %+v", id.Name, err)
return fmt.Errorf("deleting Event Grid Domain %q: %+v", id.Name, err)
}

if err = future.WaitForCompletionRef(ctx, client.Client); err != nil {
if response.WasNotFound(future.Response()) {
return nil
}
return fmt.Errorf("Error deleting Event Grid Domain %q: %+v", id.Name, err)
return fmt.Errorf("deleting Event Grid Domain %q: %+v", id.Name, err)
}

return nil
Expand Down
Expand Up @@ -89,6 +89,26 @@ func TestAccEventGridDomain_basicWithTags(t *testing.T) {
})
}

func TestAccEventGridDomain_inboundIPRules(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_eventgrid_domain", "test")
r := EventGridDomainResource{}

data.ResourceTest(t, r, []resource.TestStep{
{
Config: r.inboundIPRules(data),
Check: resource.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
check.That(data.ResourceName).Key("inbound_ip_rule.#").HasValue("2"),
check.That(data.ResourceName).Key("inbound_ip_rule.0.ip_mask").HasValue("10.0.0.0/16"),
check.That(data.ResourceName).Key("inbound_ip_rule.1.ip_mask").HasValue("10.1.0.0/16"),
check.That(data.ResourceName).Key("inbound_ip_rule.0.action").HasValue("Allow"),
check.That(data.ResourceName).Key("inbound_ip_rule.1.action").HasValue("Allow"),
),
},
data.ImportStep(),
})
}

func (EventGridDomainResource) Exists(ctx context.Context, clients *clients.Client, state *terraform.InstanceState) (*bool, error) {
id, err := parse.DomainID(state.ID)
if err != nil {
Expand Down Expand Up @@ -188,3 +208,34 @@ resource "azurerm_eventgrid_domain" "test" {
}
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger)
}

func (EventGridDomainResource) inboundIPRules(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "%s"
}
resource "azurerm_eventgrid_domain" "test" {
name = "acctesteg-%d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
public_network_access_enabled = true
inbound_ip_rule {
ip_mask = "10.0.0.0/16"
action = "Allow"
}
inbound_ip_rule {
ip_mask = "10.1.0.0/16"
action = "Allow"
}
}
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger)
}
36 changes: 26 additions & 10 deletions azurerm/internal/services/eventgrid/eventgrid_topic_resource.go
Expand Up @@ -136,6 +136,10 @@ func resourceEventGridTopic() *schema.Resource {
},
},

"public_network_access_enabled": eventSubscriptionPublicNetworkAccessEnabled(),

"inbound_ip_rule": eventSubscriptionInboundIPRule(),

"endpoint": {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -170,7 +174,7 @@ func resourceEventGridTopicCreateUpdate(d *schema.ResourceData, meta interface{}
existing, err := client.Get(ctx, resourceGroup, name)
if err != nil {
if !utils.ResponseWasNotFound(existing.Response) {
return fmt.Errorf("Error checking for presence of existing EventGrid Topic %q (Resource Group %q): %s", name, resourceGroup, err)
return fmt.Errorf("checking for presence of existing EventGrid Topic %q (Resource Group %q): %s", name, resourceGroup, err)
}
}

Expand All @@ -183,8 +187,10 @@ func resourceEventGridTopicCreateUpdate(d *schema.ResourceData, meta interface{}
t := d.Get("tags").(map[string]interface{})

topicProperties := &eventgrid.TopicProperties{
InputSchemaMapping: expandAzureRmEventgridTopicInputMapping(d),
InputSchema: eventgrid.InputSchema(d.Get("input_schema").(string)),
InputSchemaMapping: expandAzureRmEventgridTopicInputMapping(d),
InputSchema: eventgrid.InputSchema(d.Get("input_schema").(string)),
PublicNetworkAccess: expandPublicNetworkAccess(d),
InboundIPRules: expandInboundIPRules(d),
}

properties := eventgrid.Topic{
Expand All @@ -209,7 +215,7 @@ func resourceEventGridTopicCreateUpdate(d *schema.ResourceData, meta interface{}
return err
}
if read.ID == nil {
return fmt.Errorf("Cannot read EventGrid Topic %s (resource group %s) ID", name, resourceGroup)
return fmt.Errorf("reading EventGrid Topic %s (resource group %s) ID", name, resourceGroup)
}

d.SetId(*read.ID)
Expand All @@ -235,7 +241,7 @@ func resourceEventGridTopicRead(d *schema.ResourceData, meta interface{}) error
return nil
}

return fmt.Errorf("Error making Read request on EventGrid Topic '%s': %+v", id.Name, err)
return fmt.Errorf("making Read request on EventGrid Topic '%s': %+v", id.Name, err)
}
if props := resp.TopicProperties; props != nil {
d.Set("endpoint", props.Endpoint)
Expand All @@ -247,21 +253,31 @@ func resourceEventGridTopicRead(d *schema.ResourceData, meta interface{}) error
return fmt.Errorf("Unable to flatten `input_schema_mapping_fields` for EventGrid Topic %q (Resource Group %q): %s", id.Name, id.ResourceGroup, err)
}
if err := d.Set("input_mapping_fields", inputMappingFields); err != nil {
return fmt.Errorf("Error setting `input_schema_mapping_fields` for EventGrid Topic %q (Resource Group %q): %s", id.Name, id.ResourceGroup, err)
return fmt.Errorf("setting `input_schema_mapping_fields` for EventGrid Topic %q (Resource Group %q): %s", id.Name, id.ResourceGroup, err)
}

inputMappingDefaultValues, err := flattenAzureRmEventgridTopicInputMappingDefaultValues(props.InputSchemaMapping)
if err != nil {
return fmt.Errorf("Unable to flatten `input_schema_mapping_default_values` for EventGrid Topic %q (Resource Group %q): %s", id.Name, id.ResourceGroup, err)
}
if err := d.Set("input_mapping_default_values", inputMappingDefaultValues); err != nil {
return fmt.Errorf("Error setting `input_schema_mapping_fields` for EventGrid Topic %q (Resource Group %q): %s", id.Name, id.ResourceGroup, err)
return fmt.Errorf("setting `input_schema_mapping_fields` for EventGrid Topic %q (Resource Group %q): %s", id.Name, id.ResourceGroup, err)
}

publicNetworkAccessEnabled := flattenPublicNetworkAccess(props.PublicNetworkAccess)
if err := d.Set("public_network_access_enabled", publicNetworkAccessEnabled); err != nil {
return fmt.Errorf("setting `public_network_access_enabled` in EventGrid Topic %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err)
}

inboundIPRules := flattenInboundIPRules(props.InboundIPRules)
if err := d.Set("inbound_ip_rule", inboundIPRules); err != nil {
return fmt.Errorf("setting `inbound_ip_rule` in EventGrid Topic %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err)
}
}

keys, err := client.ListSharedAccessKeys(ctx, id.ResourceGroup, id.Name)
if err != nil {
return fmt.Errorf("Error retrieving Shared Access Keys for EventGrid Topic '%s': %+v", id.Name, err)
return fmt.Errorf("retrieving Shared Access Keys for EventGrid Topic '%s': %+v", id.Name, err)
}

d.Set("name", resp.Name)
Expand Down Expand Up @@ -295,14 +311,14 @@ func resourceEventGridTopicDelete(d *schema.ResourceData, meta interface{}) erro
if response.WasNotFound(future.Response()) {
return nil
}
return fmt.Errorf("Error deleting EventGrid Topic %q: %+v", id.Name, err)
return fmt.Errorf("deleting EventGrid Topic %q: %+v", id.Name, err)
}

if err = future.WaitForCompletionRef(ctx, client.Client); err != nil {
if response.WasNotFound(future.Response()) {
return nil
}
return fmt.Errorf("Error deleting EventGrid Topic %q: %+v", id.Name, err)
return fmt.Errorf("deleting EventGrid Topic %q: %+v", id.Name, err)
}

return nil
Expand Down

0 comments on commit 9387ef3

Please sign in to comment.