Skip to content

Commit

Permalink
feat: network policy v1 readiness (#2914)
Browse files Browse the repository at this point in the history
Changes:
- refactored the resource and created the data source for network policy
- changes documented in the migration guide
- examples refreshed/added

## Test Plan
<!-- detail ways in which this PR has been tested or needs to be tested
-->
* [x] acceptance tests

## References
<!-- issues documentation links, etc  -->

* [CREATE NETWORK
POLICY](https://docs.snowflake.com/en/sql-reference/sql/create-network-policy)
  • Loading branch information
sfc-gh-jcieslak authored Jul 23, 2024
1 parent 70a1c9a commit 3408c3f
Show file tree
Hide file tree
Showing 33 changed files with 1,644 additions and 425 deletions.
21 changes: 21 additions & 0 deletions MIGRATION_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,27 @@ Added a new datasource enabling querying and filtering stremlits. Notes:
The additional parameters call **DESC STREAMLIT** (with `with_describe` turned on) **per streamlit** returned by **SHOW STREAMLITS**.
It's important to limit the records and calls to Snowflake to the minimum. That's why we recommend assessing which information you need from the data source and then providing strong filters and turning off additional fields for better plan performance.

### *(new feature)* refactored snowflake_network_policy resource

No migration required.

New behavior:
- `name` is no longer marked as ForceNew parameter. When changed, now it will perform ALTER RENAME operation, instead of re-creating with the new name.
- Additional validation was added to `blocked_ip_list` to inform about specifying `0.0.0.0/0` ip. More details in the [official documentation](https://docs.snowflake.com/en/sql-reference/sql/create-network-policy#usage-notes).

New fields:
- `show_output` and `describe_output` added to hold the results returned by `SHOW` and `DESCRIBE` commands. Those fields will only be recomputed when specified fields change

### *(new feature)* snowflake_network_policies datasource

Added a new datasource enabling querying and filtering network policies. Notes:
- all results are stored in `network_policies` field.
- `like` field enables filtering.
- SHOW NETWORK POLICIES output is enclosed in `show_output` field inside `network_policies`.
- Output from **DESC NETWORK POLICY** (which can be turned off by declaring `with_describe = false`, **it's turned on by default**) is enclosed in `describe_output` field inside `network_policies`.
The additional parameters call **DESC NETWORK POLICY** (with `with_describe` turned on) **per network policy** returned by **SHOW NETWORK POLICIES**.
It's important to limit the records and calls to Snowflake to the minimum. That's why we recommend assessing which information you need from the data source and then providing strong filters and turning off additional fields for better plan performance.

## v0.92.0 ➞ v0.93.0

### general changes
Expand Down
111 changes: 111 additions & 0 deletions docs/data-sources/network_policies.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
---
page_title: "snowflake_network_policies Data Source - terraform-provider-snowflake"
subcategory: ""
description: |-
Datasource used to get details of filtered network policies. Filtering is aligned with the current possibilities for SHOW NETWORK POLICIES https://docs.snowflake.com/en/sql-reference/sql/show-network-policies query (like is supported). The results of SHOW and DESCRIBE are encapsulated in one output collection.
---

!> **V1 release candidate** This resource was reworked and is a release candidate for the V1. We do not expect significant changes in it before the V1. We will welcome any feedback and adjust the resource if needed. Any errors reported will be resolved with a higher priority. We encourage checking this resource out before the V1 release. Please follow the [migration guide](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/MIGRATION_GUIDE.md#v0920--v0930) to use it.

# snowflake_network_policies (Data Source)

Datasource used to get details of filtered network policies. Filtering is aligned with the current possibilities for [SHOW NETWORK POLICIES](https://docs.snowflake.com/en/sql-reference/sql/show-network-policies) query (`like` is supported). The results of SHOW and DESCRIBE are encapsulated in one output collection.

## Example Usage

```terraform
# Simple usage
data "snowflake_network_policies" "simple" {
}
output "simple_output" {
value = data.snowflake_network_policies.simple.network_policies
}
# Filtering (like)
data "snowflake_network_policies" "like" {
like = "network-policy-name"
}
output "like_output" {
value = data.snowflake_network_policies.like.network_policies
}
# Without additional data (to limit the number of calls make for every found network policy)
data "snowflake_network_policies" "only_show" {
# with_describe is turned on by default and it calls DESCRIBE NETWORK POLICY for every network policy found and attaches its output to network_policies.*.describe_output field
with_describe = false
}
output "only_show_output" {
value = data.snowflake_network_policies.only_show.network_policies
}
# Ensure the number of network policies is equal to at least one element (with the use of postcondition)
data "snowflake_network_policies" "assert_with_postcondition" {
starts_with = "network-policy-name"
lifecycle {
postcondition {
condition = length(self.network_policies) > 0
error_message = "there should be at least one network policy"
}
}
}
# Ensure the number of network policies is equal to at exactly one element (with the use of check block)
check "network_policy_check" {
data "snowflake_network_policies" "assert_with_check_block" {
like = "network-policy-name"
}
assert {
condition = length(data.snowflake_network_policies.assert_with_check_block.network_policies) == 1
error_message = "Network policies filtered by '${data.snowflake_network_policies.assert_with_check_block.like}' returned ${length(data.snowflake_network_policies.assert_with_check_block.network_policies)} network policies where one was expected"
}
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Optional

- `like` (String) Filters the output with **case-insensitive** pattern, with support for SQL wildcard characters (`%` and `_`).
- `with_describe` (Boolean) Runs DESC NETWORK POLICY for each network policy returned by SHOW NETWORK POLICIES. The output of describe is saved to the description field. By default this value is set to true.

### Read-Only

- `id` (String) The ID of this resource.
- `network_policies` (List of Object) Holds the aggregated output of all network policies details queries. (see [below for nested schema](#nestedatt--network_policies))

<a id="nestedatt--network_policies"></a>
### Nested Schema for `network_policies`

Read-Only:

- `describe_output` (List of Object) (see [below for nested schema](#nestedobjatt--network_policies--describe_output))
- `show_output` (List of Object) (see [below for nested schema](#nestedobjatt--network_policies--show_output))

<a id="nestedobjatt--network_policies--describe_output"></a>
### Nested Schema for `network_policies.describe_output`

Read-Only:

- `allowed_ip_list` (String)
- `allowed_network_rule_list` (String)
- `blocked_ip_list` (String)
- `blocked_network_rule_list` (String)


<a id="nestedobjatt--network_policies--show_output"></a>
### Nested Schema for `network_policies.show_output`

Read-Only:

- `comment` (String)
- `created_on` (String)
- `entries_in_allowed_ip_list` (Number)
- `entries_in_allowed_network_rules` (Number)
- `entries_in_blocked_ip_list` (Number)
- `entries_in_blocked_network_rules` (Number)
- `name` (String)
77 changes: 43 additions & 34 deletions docs/resources/network_policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,48 +2,31 @@
page_title: "snowflake_network_policy Resource - terraform-provider-snowflake"
subcategory: ""
description: |-
Resource used to control network traffic. For more information, check an official guide https://docs.snowflake.com/en/user-guide/network-policies on controlling network traffic with network policies.
---

# snowflake_network_policy (Resource)
!> **V1 release candidate** This resource was reworked and is a release candidate for the V1. We do not expect significant changes in it before the V1. We will welcome any feedback and adjust the resource if needed. Any errors reported will be resolved with a higher priority. We encourage checking this resource out before the V1 release. Please follow the [migration guide](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/MIGRATION_GUIDE.md#v0920--v0930) to use it.

# snowflake_network_policy (Resource)

Resource used to control network traffic. For more information, check an [official guide](https://docs.snowflake.com/en/user-guide/network-policies) on controlling network traffic with network policies.

## Example Usage

```terraform
##################################
### using network rules
##################################
resource "snowflake_network_rule" "rule" {
name = "rule"
database = "EXAMPLE_DB"
schema = "EXAMPLE_SCHEMA"
comment = "A rule."
type = "IPV4"
mode = "INGRESS"
value_list = ["192.168.0.100/24", "29.254.123.20"]
}
resource "snowflake_network_policy" "policy" {
name = "policy"
comment = "A policy."
allowed_network_rule_list = [snowflake_network_rule.rule.qualified_name]
## Minimal
resource "snowflake_network_policy" "basic" {
name = "network_policy_name"
}
##################################
### using ip lists
##################################
resource "snowflake_network_policy" "policy" {
name = "policy"
comment = "A policy."
allowed_ip_list = ["192.168.0.100/24"]
blocked_ip_list = ["192.168.0.101"]
## Complete (with every optional set)
resource "snowflake_network_policy" "basic" {
name = "network_policy_name"
allowed_network_rule_list = ["<fully qualified network rule id>"]
blocked_network_rule_list = ["<fully qualified network rule id>"]
allowed_ip_list = ["192.168.1.0/24"]
blocked_ip_list = ["192.168.1.99"]
comment = "my network policy"
}
```

Expand All @@ -58,18 +41,44 @@ resource "snowflake_network_policy" "policy" {

- `allowed_ip_list` (Set of String) Specifies one or more IPv4 addresses (CIDR notation) that are allowed access to your Snowflake account.
- `allowed_network_rule_list` (Set of String) Specifies a list of fully qualified network rules that contain the network identifiers that are allowed access to Snowflake.
- `blocked_ip_list` (Set of String) Specifies one or more IPv4 addresses (CIDR notation) that are denied access to your Snowflake account<br><br>**Do not** add `0.0.0.0/0` to `blocked_ip_list`.
- `blocked_ip_list` (Set of String) Specifies one or more IPv4 addresses (CIDR notation) that are denied access to your Snowflake account. **Do not** add `0.0.0.0/0` to `blocked_ip_list`, in order to block all IP addresses except a select list, you only need to add IP addresses to `allowed_ip_list`.
- `blocked_network_rule_list` (Set of String) Specifies a list of fully qualified network rules that contain the network identifiers that are denied access to Snowflake.
- `comment` (String) Specifies a comment for the network policy.

### Read-Only

- `describe_output` (List of Object) Outputs the result of `DESCRIBE NETWORK POLICY` for the given network policy. (see [below for nested schema](#nestedatt--describe_output))
- `id` (String) The ID of this resource.
- `show_output` (List of Object) Outputs the result of `SHOW NETWORK POLICIES` for the given network policy. (see [below for nested schema](#nestedatt--show_output))

<a id="nestedatt--describe_output"></a>
### Nested Schema for `describe_output`

Read-Only:

- `allowed_ip_list` (String)
- `allowed_network_rule_list` (String)
- `blocked_ip_list` (String)
- `blocked_network_rule_list` (String)


<a id="nestedatt--show_output"></a>
### Nested Schema for `show_output`

Read-Only:

- `comment` (String)
- `created_on` (String)
- `entries_in_allowed_ip_list` (Number)
- `entries_in_allowed_network_rules` (Number)
- `entries_in_blocked_ip_list` (Number)
- `entries_in_blocked_network_rules` (Number)
- `name` (String)

## Import

Import is supported using the following syntax:

```shell
terraform import snowflake_network_policy.example policyname
terraform import snowflake_network_policy.example "name"
```
49 changes: 49 additions & 0 deletions examples/data-sources/snowflake_network_policies/data-source.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Simple usage
data "snowflake_network_policies" "simple" {
}

output "simple_output" {
value = data.snowflake_network_policies.simple.network_policies
}

# Filtering (like)
data "snowflake_network_policies" "like" {
like = "network-policy-name"
}

output "like_output" {
value = data.snowflake_network_policies.like.network_policies
}

# Without additional data (to limit the number of calls make for every found network policy)
data "snowflake_network_policies" "only_show" {
# with_describe is turned on by default and it calls DESCRIBE NETWORK POLICY for every network policy found and attaches its output to network_policies.*.describe_output field
with_describe = false
}

output "only_show_output" {
value = data.snowflake_network_policies.only_show.network_policies
}

# Ensure the number of network policies is equal to at least one element (with the use of postcondition)
data "snowflake_network_policies" "assert_with_postcondition" {
starts_with = "network-policy-name"
lifecycle {
postcondition {
condition = length(self.network_policies) > 0
error_message = "there should be at least one network policy"
}
}
}

# Ensure the number of network policies is equal to at exactly one element (with the use of check block)
check "network_policy_check" {
data "snowflake_network_policies" "assert_with_check_block" {
like = "network-policy-name"
}

assert {
condition = length(data.snowflake_network_policies.assert_with_check_block.network_policies) == 1
error_message = "Network policies filtered by '${data.snowflake_network_policies.assert_with_check_block.like}' returned ${length(data.snowflake_network_policies.assert_with_check_block.network_policies)} network policies where one was expected"
}
}
2 changes: 1 addition & 1 deletion examples/resources/snowflake_network_policy/import.sh
Original file line number Diff line number Diff line change
@@ -1 +1 @@
terraform import snowflake_network_policy.example policyname
terraform import snowflake_network_policy.example "name"
43 changes: 12 additions & 31 deletions examples/resources/snowflake_network_policy/resource.tf
Original file line number Diff line number Diff line change
@@ -1,33 +1,14 @@
##################################
### using network rules
##################################

resource "snowflake_network_rule" "rule" {
name = "rule"
database = "EXAMPLE_DB"
schema = "EXAMPLE_SCHEMA"
comment = "A rule."
type = "IPV4"
mode = "INGRESS"
value_list = ["192.168.0.100/24", "29.254.123.20"]
}

resource "snowflake_network_policy" "policy" {
name = "policy"
comment = "A policy."

allowed_network_rule_list = [snowflake_network_rule.rule.qualified_name]
## Minimal
resource "snowflake_network_policy" "basic" {
name = "network_policy_name"
}


##################################
### using ip lists
##################################

resource "snowflake_network_policy" "policy" {
name = "policy"
comment = "A policy."

allowed_ip_list = ["192.168.0.100/24"]
blocked_ip_list = ["192.168.0.101"]
}
## Complete (with every optional set)
resource "snowflake_network_policy" "basic" {
name = "network_policy_name"
allowed_network_rule_list = ["<fully qualified network rule id>"]
blocked_network_rule_list = ["<fully qualified network rule id>"]
allowed_ip_list = ["192.168.1.0/24"]
blocked_ip_list = ["192.168.1.99"]
comment = "my network policy"
}
10 changes: 9 additions & 1 deletion pkg/acceptance/helpers/network_policy_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,20 @@ func (c *NetworkPolicyClient) CreateNetworkPolicyWithRequest(t *testing.T, reque
return networkPolicy, c.DropNetworkPolicyFunc(t, request.GetName())
}

func (c *NetworkPolicyClient) Update(t *testing.T, request *sdk.AlterNetworkPolicyRequest) {
t.Helper()
ctx := context.Background()

err := c.client().Alter(ctx, request)
require.NoError(t, err)
}

func (c *NetworkPolicyClient) DropNetworkPolicyFunc(t *testing.T, id sdk.AccountObjectIdentifier) func() {
t.Helper()
ctx := context.Background()

return func() {
err := c.client().Drop(ctx, sdk.NewDropNetworkPolicyRequest(id).WithIfExists(sdk.Bool(true)))
err := c.client().Drop(ctx, sdk.NewDropNetworkPolicyRequest(id).WithIfExists(true))
require.NoError(t, err)
}
}
Loading

0 comments on commit 3408c3f

Please sign in to comment.