diff --git a/internal/services/search/search_service_resource.go b/internal/services/search/search_service_resource.go index ce31fe1b1e5b..48dfe8f99bbe 100644 --- a/internal/services/search/search_service_resource.go +++ b/internal/services/search/search_service_resource.go @@ -187,6 +187,16 @@ func resourceSearchService() *pluginsdk.Resource { }, }, + "network_rule_bypass_option": { + Type: pluginsdk.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{ + string(services.SearchBypassAzureServices), + string(services.SearchBypassNone), + }, false), + Default: string(services.SearchBypassNone), + }, + "identity": commonschema.SystemAssignedUserAssignedIdentityOptional(), "tags": commonschema.Tags(), @@ -223,6 +233,7 @@ func resourceSearchServiceCreate(d *pluginsdk.ResourceData, meta interface{}) er cmkEnforcementEnabled := d.Get("customer_managed_key_enforcement_enabled").(bool) localAuthenticationEnabled := d.Get("local_authentication_enabled").(bool) authenticationFailureMode := d.Get("authentication_failure_mode").(string) + networkRuleBypassOptions := services.SearchBypass(d.Get("network_rule_bypass_option").(string)) semanticSearchSku := services.SearchSemanticSearchDisabled if v := d.Get("semantic_search_sku").(string); v != "" { @@ -302,6 +313,7 @@ func resourceSearchServiceCreate(d *pluginsdk.ResourceData, meta interface{}) er PublicNetworkAccess: pointer.To(publicNetworkAccess), NetworkRuleSet: pointer.To(services.NetworkRuleSet{ IPRules: expandSearchServiceIPRules(ipRulesRaw), + Bypass: pointer.To(networkRuleBypassOptions), }), EncryptionWithCmk: pointer.To(services.EncryptionWithCmk{ Enforcement: pointer.To(cmkEnforcement), @@ -484,6 +496,14 @@ func resourceSearchServiceUpdate(d *pluginsdk.ResourceData, meta interface{}) er } } + if d.HasChange("network_rule_bypass_option") { + networkBypassOptions := services.SearchBypass(d.Get("network_rule_bypass_option").(string)) + if model.Properties.NetworkRuleSet == nil { + model.Properties.NetworkRuleSet = &services.NetworkRuleSet{} + } + model.Properties.NetworkRuleSet.Bypass = pointer.To(networkBypassOptions) + } + if d.HasChange("semantic_search_sku") { semanticSearchSku := services.SearchSemanticSearchDisabled if v := d.Get("semantic_search_sku").(string); v != "" { @@ -604,6 +624,10 @@ func resourceSearchServiceRead(d *pluginsdk.ResourceData, meta interface{}) erro d.Set("customer_managed_key_enforcement_enabled", cmkEnforcement) d.Set("allowed_ips", flattenSearchServiceIPRules(props.NetworkRuleSet)) d.Set("semantic_search_sku", semanticSearchSku) + + if props.NetworkRuleSet != nil { + d.Set("network_rule_bypass_option", string(pointer.From(props.NetworkRuleSet.Bypass))) + } } flattenedIdentity, err := identity.FlattenSystemAndUserAssignedMap(model.Identity) diff --git a/internal/services/search/search_service_resource_test.go b/internal/services/search/search_service_resource_test.go index fade7b980eca..ff854c45eb68 100644 --- a/internal/services/search/search_service_resource_test.go +++ b/internal/services/search/search_service_resource_test.go @@ -213,6 +213,35 @@ func TestAccSearchService_ipRules(t *testing.T) { }) } +func TestAccSearchService_bypassServices(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_search_service", "test") + r := SearchServiceResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data, "standard"), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.bypassServices(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.basic(data, "standard"), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + func TestAccSearchService_identity(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_search_service", "test") r := SearchServiceResource{} @@ -699,6 +728,25 @@ resource "azurerm_search_service" "test" { `, template, data.RandomInteger) } +func (r SearchServiceResource) bypassServices(data acceptance.TestData) string { + template := r.template(data) + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +%s + +resource "azurerm_search_service" "test" { + name = "acctestsearchservice%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + sku = "standard" + network_rule_bypass_option = "AzureServices" +} +`, template, data.RandomInteger) +} + func (r SearchServiceResource) identity(data acceptance.TestData) string { template := r.template(data) return fmt.Sprintf(` diff --git a/website/docs/r/search_service.html.markdown b/website/docs/r/search_service.html.markdown index d17874f6d4f4..7473cb54f856 100644 --- a/website/docs/r/search_service.html.markdown +++ b/website/docs/r/search_service.html.markdown @@ -100,6 +100,8 @@ The following arguments are supported: * `local_authentication_enabled` - (Optional) Specifies whether the Search Service allows authenticating using API Keys? Defaults to `true`. +* `network_rule_bypass_option` - (Optional) Whether to allow trusted Azure services to access a network restricted Container Registry? Possible values are `None` and `AzureServices`. Defaults to `None`. + * `partition_count` - (Optional) Specifies the number of partitions which should be created. This field cannot be set when using a `free` sku ([see the Microsoft documentation](https://learn.microsoft.com/azure/search/search-sku-tier)). Possible values include `1`, `2`, `3`, `4`, `6`, or `12`. Defaults to `1`. -> **NOTE:** when `hosting_mode` is set to `highDensity` the maximum number of partitions allowed is `3`.