Skip to content

Commit

Permalink
Add support for network polices (#669)
Browse files Browse the repository at this point in the history
  • Loading branch information
bobbyiliev authored Nov 13, 2024
1 parent 4f61ea1 commit 5be5c2b
Show file tree
Hide file tree
Showing 23 changed files with 1,427 additions and 2 deletions.
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.

### 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

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

0 comments on commit 5be5c2b

Please sign in to comment.