Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for network polices #669

Merged
merged 6 commits into from
Nov 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions docs/data-sources/network_policy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "materialize_network_policy Data Source - terraform-provider-materialize"
subcategory: ""
description: |-
A network policy data source. This can be used to get information about all network policies in Materialize.
---

# materialize_network_policy (Data Source)

A network policy data source. This can be used to get information about all network policies in Materialize.

## Example Usage

```terraform
data "materialize_network_policy" "all" {}
```

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

### Optional

- `region` (String) The region in which the resource is located.

### Read-Only

- `id` (String) The ID of this resource.
- `network_policies` (List of Object) The network policies in the account (see [below for nested schema](#nestedatt--network_policies))

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

Read-Only:

- `comment` (String)
- `id` (String)
- `name` (String)
- `rules` (List of Object) (see [below for nested schema](#nestedobjatt--network_policies--rules))

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

Read-Only:

- `action` (String)
- `address` (String)
- `direction` (String)
- `name` (String)
6 changes: 6 additions & 0 deletions docs/resources/grant_system_privilege.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ resource "materialize_grant_system_privilege" "role_createdb" {
role_name = "role"
privilege = "CREATEDB"
}

# Grant role the privilege CREATENETWORKPOLICY to allow the role to create network policies
resource "materialize_grant_system_privilege" "role_createnetworkpolicy" {
role_name = "role"
privilege = "CREATENETWORKPOLICY"
}
```

<!-- schema generated by tfplugindocs -->
Expand Down
75 changes: 75 additions & 0 deletions docs/resources/network_policy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "materialize_network_policy Resource - terraform-provider-materialize"
subcategory: ""
description: |-
A network policy manages access to the system through IP-based rules.
---

# materialize_network_policy (Resource)

A network policy manages access to the system through IP-based rules.

## Example Usage

```terraform
resource "materialize_network_policy" "office_policy" {
name = "office_access_policy"

rule {
name = "minnesota"
action = "allow"
direction = "ingress"
address = "2.3.4.5/32"
}

rule {
name = "new_york"
action = "allow"
direction = "ingress"
address = "1.2.3.4/28"
}

comment = "Network policy for office locations"
}
```

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

### Required

- `name` (String) The name of the network policy.
- `rule` (Block Set, Min: 1, Max: 25) Rules for the network policy. (see [below for nested schema](#nestedblock--rule))

### Optional

- `comment` (String) **Public Preview** Comment on an object in the database.
- `region` (String) The region to use for the resource connection. If not set, the default region is used.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm unfamiliar with the Terraform provider, is region a field we typically allow folks to specify?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, this was introduced last year when we refactored the provider, this allows users to manage cross region instances within the same terraform project.

For example:

resource "materialize_database" "database" {
  name    = "example_database"
  comment = "database comment"
}

# Create in separate region
resource "materialize_database" "database_us_west" {
  name    = "example_database"
  comment = "database comment"
  region  = "aws/us-west-2"
}

the first one will create the db in the default region defined in the provider configuration, but the second one overrides the region and will create the db in aws/us-west-2 if it is enabled.


### Read-Only

- `id` (String) The ID of this resource.

<a id="nestedblock--rule"></a>
### Nested Schema for `rule`

Required:

- `action` (String) The action to take for this rule. Currently only 'allow' is supported.
- `address` (String) The CIDR block the rule will be applied to.
- `direction` (String) The direction of traffic the rule applies to. Currently only 'ingress' is supported.
- `name` (String) The name of the rule.

## Import

Import is supported using the following syntax:

```shell
# Network policies can be imported using the `terraform import` command.
terraform import materialize_network_policy.example_network_policy <region>:<network_policy_id>

# The network_policy_id is the ID of the network policy.
# You can find it from the `mz_internal.mz_network_policy_rules` table in the materialize
# The region is the region where the database is located (e.g. aws/us-east-1)
```
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
data "materialize_network_policy" "all" {}
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,9 @@ resource "materialize_grant_system_privilege" "role_createdb" {
role_name = "role"
privilege = "CREATEDB"
}

# Grant role the privilege CREATENETWORKPOLICY to allow the role to create network policies
resource "materialize_grant_system_privilege" "role_createnetworkpolicy" {
role_name = "role"
privilege = "CREATENETWORKPOLICY"
}
6 changes: 6 additions & 0 deletions examples/resources/materialize_network_policy/import.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Network policies can be imported using the `terraform import` command.
terraform import materialize_network_policy.example_network_policy <region>:<network_policy_id>

# The network_policy_id is the ID of the network policy.
# You can find it from the `mz_internal.mz_network_policy_rules` table in the materialize
# The region is the region where the database is located (e.g. aws/us-east-1)
19 changes: 19 additions & 0 deletions examples/resources/materialize_network_policy/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
resource "materialize_network_policy" "office_policy" {
name = "office_access_policy"

rule {
name = "minnesota"
action = "allow"
direction = "ingress"
address = "2.3.4.5/32"
}

rule {
name = "new_york"
action = "allow"
direction = "ingress"
address = "1.2.3.4/28"
}

comment = "Network policy for office locations"
}
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module github.com/MaterializeInc/terraform-provider-materialize

go 1.22.0
go 1.22.7
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just double checking, is this kind of upgrade a breaking change? /compatible with how we're changing the version of the terraform provider?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, this minor version upgrade should be ok, it was needed because of a recent dependabot commit:

4f61ea1

Kind of sneaking the bump into this PR 😅


toolchain go1.22.9

require (
Expand Down
20 changes: 20 additions & 0 deletions integration/network_policy.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
resource "materialize_network_policy" "office_policy" {
name = "office_access_policy"

rule {
name = "minnesota"
action = "allow"
direction = "ingress"
address = "2.3.4.5/32"
}

rule {
name = "new_york"
action = "allow"
direction = "ingress"
address = "1.2.3.4/28"
}


comment = "Network policy for office locations"
}
120 changes: 120 additions & 0 deletions pkg/datasources/datasource_network_policy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package datasources

import (
"context"

"github.com/MaterializeInc/terraform-provider-materialize/pkg/materialize"
"github.com/MaterializeInc/terraform-provider-materialize/pkg/utils"

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func NetworkPolicy() *schema.Resource {
return &schema.Resource{
ReadContext: networkPolicyRead,
Description: "A network policy data source. This can be used to get information about all network policies in Materialize.",
Schema: map[string]*schema.Schema{
"network_policies": {
Type: schema.TypeList,
Computed: true,
Description: "The network policies in the account",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"id": {
Type: schema.TypeString,
Description: "The ID of the network policy.",
Computed: true,
},
"name": {
Type: schema.TypeString,
Description: "The name of the network policy.",
Computed: true,
},
"comment": {
Type: schema.TypeString,
Description: "The comment of the network policy.",
Computed: true,
},
"rules": {
Type: schema.TypeList,
Description: "Rules for the network policy.",
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Description: "The name of the rule.",
Computed: true,
},
"action": {
Type: schema.TypeString,
Description: "The action to take for this rule. Currently only 'allow' is supported.",
Computed: true,
},
"direction": {
Type: schema.TypeString,
Description: "The direction of traffic the rule applies to. Currently only 'ingress' is supported.",
Computed: true,
},
"address": {
Type: schema.TypeString,
Description: "The CIDR block the rule will be applied to.",
Computed: true,
},
},
},
},
},
},
},
"region": RegionSchema(),
},
}
}

func networkPolicyRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var diags diag.Diagnostics

metaDb, region, err := utils.GetDBClientFromMeta(meta, d)
if err != nil {
return diag.FromErr(err)
}

// Add List function to materialize package
networkPolicy, err := materialize.ListNetworkPolicies(metaDb)
if err != nil {
return diag.FromErr(err)
}

networkPolicyFormatted := []map[string]interface{}{}
for _, p := range networkPolicy {
networkPolicyMap := map[string]interface{}{}

networkPolicyMap["id"] = p.PolicyId.String
networkPolicyMap["name"] = p.PolicyName.String
networkPolicyMap["comment"] = p.Comment.String

// Format rules
rules := []map[string]interface{}{}
for _, r := range p.Rules {
ruleMap := map[string]interface{}{
"name": r.Name,
"action": r.Action,
"direction": r.Direction,
"address": r.Address,
}
rules = append(rules, ruleMap)
}
networkPolicyMap["rules"] = rules

networkPolicyFormatted = append(networkPolicyFormatted, networkPolicyMap)
}

if err := d.Set("network_policies", networkPolicyFormatted); err != nil {
return diag.FromErr(err)
}

d.SetId(utils.TransformIdWithRegion(string(region), "network_policies"))
return diags
}
55 changes: 55 additions & 0 deletions pkg/datasources/datasource_network_policy_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package datasources

import (
"context"
"testing"

"github.com/MaterializeInc/terraform-provider-materialize/pkg/testhelpers"
"github.com/MaterializeInc/terraform-provider-materialize/pkg/utils"

"github.com/DATA-DOG/go-sqlmock"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/stretchr/testify/require"
)

func TestNetworkPolicyDatasource(t *testing.T) {
r := require.New(t)

// Empty input map since we're not filtering
in := map[string]interface{}{}
d := schema.TestResourceDataRaw(t, NetworkPolicy().Schema, in)
r.NotNil(d)

testhelpers.WithMockProviderMeta(t, func(db *utils.ProviderMeta, mock sqlmock.Sqlmock) {
// No predicates since we're listing all policies
testhelpers.MockNetworkPolicyScan(mock, "")

if err := networkPolicyRead(context.TODO(), d, db); err != nil {
t.Fatal(err)
}

// Verify the data source output
policies := d.Get("network_policies").([]interface{})
r.Equal(1, len(policies))

policy := policies[0].(map[string]interface{})
r.Equal("u1", policy["id"])
r.Equal("office_policy", policy["name"])
r.Equal("Network policy for office locations", policy["comment"])

rules := policy["rules"].([]interface{})
r.Equal(2, len(rules))

rule1 := rules[0].(map[string]interface{})
r.Equal("minnesota", rule1["name"])
r.Equal("allow", rule1["action"])
r.Equal("ingress", rule1["direction"])
r.Equal("2.3.4.5/32", rule1["address"])

rule2 := rules[1].(map[string]interface{})
r.Equal("new_york", rule2["name"])
r.Equal("allow", rule2["action"])
r.Equal("ingress", rule2["direction"])
r.Equal("1.2.3.4/28", rule2["address"])
})
}
1 change: 1 addition & 0 deletions pkg/materialize/generic.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const (
BaseType EntityType = "TYPE"
View EntityType = "VIEW"
System EntityType = "SYSTEM"
NetworkPolicy EntityType = "NETWORK POLICY"
)

type Builder struct {
Expand Down
Loading
Loading