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

Feature: add support for DLP policies #577

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
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/dlp_policies.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: "twingate_dlp_policies Data Source - terraform-provider-twingate"
subcategory: ""
description: |-
DLP policies are currently in early access. For more information, reach out to your account manager.
---

# twingate_dlp_policies (Data Source)

DLP policies are currently in early access. For more information, reach out to your account manager.

## Example Usage

```terraform
data "twingate_dlp_policies" "foo" {
name = "<your DLP policy name>"
# name_regexp = "<regular expression of DLP policy name>"
# name_contains = "<a string in the DLP policy name>"
# name_exclude = "<your DLP policy name to exclude>"
# name_prefix = "<prefix of DLP policy name>"
# name_suffix = "<suffix of DLP policy name>"
}
```

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

### Optional

- `name` (String) Returns only DLP policies that exactly match this name. If no options are passed, returns all DLP policies.
- `name_contains` (String) Returns only DLP policies that contain this string.
- `name_exclude` (String) Returns only DLP policies that do not include this string.
- `name_prefix` (String) Returns only DLP policies that start in this string.
- `name_regexp` (String) Returns only DLP policies that satisfy this regex.
- `name_suffix` (String) Returns only DLP policies that end in this string.

### Read-Only

- `dlp_policies` (Attributes List) List of DLP policies (see [below for nested schema](#nestedatt--dlp_policies))
- `id` (String) The ID of this data source.

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

Read-Only:

- `id` (String) The ID of the DLP policy
- `name` (String) The name of the DLP policy
30 changes: 30 additions & 0 deletions docs/data-sources/dlp_policy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "twingate_dlp_policy Data Source - terraform-provider-twingate"
subcategory: ""
description: |-
DLP policies are currently in early access. For more information, reach out to your account manager.
---

# twingate_dlp_policy (Data Source)

DLP policies are currently in early access. For more information, reach out to your account manager.

## Example Usage

```terraform
data "twingate_dlp_policy" "foo" {
id = "<your DLP policy id>"
# name = "<your DLP policy name>"
}

# DLP policy can be queried by name or id
```

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

### Optional

- `id` (String) The DLP policy's ID. Returns a DLP policy that has this ID.
- `name` (String) The DLP policy's name. Returns a DLP policy that exactly matches this name.
10 changes: 9 additions & 1 deletion docs/resources/resource.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,17 @@ data "twingate_security_policy" "test_policy" {
name = "Test Policy"
}

data twingate_dlp_policy access_example {
name = "DLP Policy Access Example"
}

resource "twingate_resource" "resource" {
name = "network"
address = "internal.int"
remote_network_id = twingate_remote_network.aws_network.id

security_policy_id = data.twingate_security_policy.test_policy.id
dlp_policy_id = data.twingate_dlp_policy.access_example.id

protocols = {
allow_icmp = true
Expand All @@ -69,6 +74,7 @@ resource "twingate_resource" "resource" {
group_id = twingate_group.aws.id
security_policy_id = data.twingate_security_policy.test_policy.id
usage_based_autolock_duration_days = 30
dlp_policy_id = data.twingate_dlp_policy.access_example.id
}

// Adding multiple groups by individual ID
Expand Down Expand Up @@ -98,7 +104,7 @@ resource "twingate_resource" "resource" {
}

// Service acoount access is specified similarly
// A `for_each` block may be used like above to assign access to multiple
// A `for_each` block may be used like above to assign access to multiple
// service accounts in a single configuration block.
access_service {
content {
Expand All @@ -124,6 +130,7 @@ resource "twingate_resource" "resource" {
- `access_group` (Block Set) Restrict access to certain group (see [below for nested schema](#nestedblock--access_group))
- `access_service` (Block Set) Restrict access to certain service account (see [below for nested schema](#nestedblock--access_service))
- `alias` (String) Set a DNS alias address for the Resource. Must be a DNS-valid name string.
- `dlp_policy_id` (String) The ID of a DLP policy to be used as the default DLP policy for this Resource. Defaults to null.
- `is_active` (Boolean) Set the resource as active or inactive. Default is `true`.
- `is_authoritative` (Boolean) Determines whether assignments in the access block will override any existing assignments. Default is `true`. If set to `false`, assignments made outside of Terraform will be ignored.
- `is_browser_shortcut_enabled` (Boolean) Controls whether an "Open in Browser" shortcut will be shown for this Resource in the Twingate Client. Default is `false`.
Expand All @@ -140,6 +147,7 @@ resource "twingate_resource" "resource" {

Optional:

- `dlp_policy_id` (String) The ID of a DLP policy to be used as the DLP policy for the group in this access block.
- `group_id` (String) Group ID that will have permission to access the Resource.
- `security_policy_id` (String) The ID of a `twingate_security_policy` to use as the access policy for the group IDs in the access block.
- `usage_based_autolock_duration_days` (Number) The usage-based auto-lock duration configured on the edge (in days).
Expand Down
8 changes: 8 additions & 0 deletions examples/data-sources/twingate_dlp_policies/data-source.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
data "twingate_dlp_policies" "foo" {
name = "<your DLP policy name>"
# name_regexp = "<regular expression of DLP policy name>"
# name_contains = "<a string in the DLP policy name>"
# name_exclude = "<your DLP policy name to exclude>"
# name_prefix = "<prefix of DLP policy name>"
# name_suffix = "<suffix of DLP policy name>"
}
6 changes: 6 additions & 0 deletions examples/data-sources/twingate_dlp_policy/data-source.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
data "twingate_dlp_policy" "foo" {
id = "<your DLP policy id>"
# name = "<your DLP policy name>"
}

# DLP policy can be queried by name or id
9 changes: 7 additions & 2 deletions examples/resources/twingate_resource/resource.tf
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,17 @@ data "twingate_security_policy" "test_policy" {
name = "Test Policy"
}

data twingate_dlp_policy access_example {
name = "DLP Policy Access Example"
}

resource "twingate_resource" "resource" {
name = "network"
address = "internal.int"
remote_network_id = twingate_remote_network.aws_network.id

security_policy_id = data.twingate_security_policy.test_policy.id
dlp_policy_id = data.twingate_dlp_policy.access_example.id

protocols = {
allow_icmp = true
Expand All @@ -54,6 +59,7 @@ resource "twingate_resource" "resource" {
group_id = twingate_group.aws.id
security_policy_id = data.twingate_security_policy.test_policy.id
usage_based_autolock_duration_days = 30
dlp_policy_id = data.twingate_dlp_policy.access_example.id
}

// Adding multiple groups by individual ID
Expand Down Expand Up @@ -83,7 +89,7 @@ resource "twingate_resource" "resource" {
}

// Service acoount access is specified similarly
// A `for_each` block may be used like above to assign access to multiple
// A `for_each` block may be used like above to assign access to multiple
// service accounts in a single configuration block.
access_service {
content {
Expand All @@ -93,4 +99,3 @@ resource "twingate_resource" "resource" {

is_active = true
}

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/Twingate/terraform-provider-twingate/v3

go 1.22
go 1.22.0

toolchain go1.22.5

require (
Expand Down
3 changes: 3 additions & 0 deletions twingate/internal/attr/dlp-policy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package attr

const DLPPolicies = "dlp_policies"
1 change: 1 addition & 0 deletions twingate/internal/attr/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ const (
IsVisible = "is_visible"
IsBrowserShortcutEnabled = "is_browser_shortcut_enabled"
Resources = "resources"
DLPPolicyID = "dlp_policy_id"
)
65 changes: 65 additions & 0 deletions twingate/internal/client/dlp-policy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package client

import (
"context"

"github.com/Twingate/terraform-provider-twingate/v3/twingate/internal/client/query"
"github.com/Twingate/terraform-provider-twingate/v3/twingate/internal/model"
)

func (client *Client) ReadDLPPolicy(ctx context.Context, policy *model.DLPPolicy) (*model.DLPPolicy, error) {
opr := resourceDLPPolicy.read()

if policy == nil || policy.ID == "" && policy.Name == "" {
return nil, opr.apiError(ErrGraphqlEmptyBothNameAndID)
}

variables := newVars(
gqlNullableID(policy.ID, "id"),
gqlNullable(policy.Name, "name"),
)

response := query.ReadDLPPolicy{}
if err := client.query(ctx, &response, variables, opr, attr{id: policy.ID, name: policy.Name}); err != nil {
return nil, err
}

return response.ToModel(), nil
}

func (client *Client) ReadDLPPolicies(ctx context.Context, name, filter string) ([]*model.DLPPolicy, error) {
opr := resourceDLPPolicy.read().withCustomName("readDLPPolicies")

variables := newVars(
gqlNullable(query.NewDLPPoliciesFilterInput(name, filter), "filter"),
cursor(query.CursorDLPPolicies),
pageLimit(client.pageLimit),
)

response := query.ReadDLPPolicies{}
if err := client.query(ctx, &response, variables, opr,
attr{id: "All", name: name}); err != nil {
return nil, err
}

oprCtx := withOperationCtx(ctx, opr)

if err := response.FetchPages(oprCtx, client.readDLPPoliciesAfter, variables); err != nil {
return nil, err //nolint
}

return response.ToModel(), nil
}

func (client *Client) readDLPPoliciesAfter(ctx context.Context, variables map[string]interface{}, cursor string) (*query.PaginatedResource[*query.DLPPolicyEdge], error) {
opr := resourceDLPPolicy.read().withCustomName("readDLPPoliciesAfter")

variables[query.CursorDLPPolicies] = cursor

response := query.ReadDLPPolicies{}
if err := client.query(ctx, &response, variables, opr, attr{id: "All"}); err != nil {
return nil, err
}

return &response.PaginatedResource, nil
}
1 change: 1 addition & 0 deletions twingate/internal/client/operation.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const (
resourceServiceKey resource = "service account key"
resourceUser resource = "user"
resourceDNSFilteringProfile resource = "DNS filtering profile"
resourceDLPPolicy resource = "dlp policy"
)

const (
Expand Down
4 changes: 4 additions & 0 deletions twingate/internal/client/query/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ type IDName struct {
Name string `json:"name"`
}

func (node IDName) GetID() string {
return string(node.ID)
}

type OkError struct {
Ok bool `json:"ok"`
Error string `json:"error"`
Expand Down
40 changes: 40 additions & 0 deletions twingate/internal/client/query/dlp-policies-read.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package query

import (
"github.com/Twingate/terraform-provider-twingate/v3/twingate/internal/model"
"github.com/Twingate/terraform-provider-twingate/v3/twingate/internal/utils"
)

type DataLossPreventionPolicyFilterInput struct {
Name *StringFilterOperationInput `json:"name"`
}

func NewDLPPoliciesFilterInput(name, filter string) *DataLossPreventionPolicyFilterInput {
return &DataLossPreventionPolicyFilterInput{
Name: NewStringFilterOperationInput(name, filter),
}
}

const CursorDLPPolicies = "dlpPoliciesEndCursor"

type ReadDLPPolicies struct {
DLPPolicies `graphql:"dlpPolicies(filter: $filter, after: $dlpPoliciesEndCursor, first: $pageLimit)"`
}

type DLPPolicies struct {
PaginatedResource[*DLPPolicyEdge]
}

type DLPPolicyEdge struct {
Node *gqlDLPPolicy
}

func (r ReadDLPPolicies) ToModel() []*model.DLPPolicy {
return utils.Map[*DLPPolicyEdge, *model.DLPPolicy](r.Edges, func(edge *DLPPolicyEdge) *model.DLPPolicy {
return edge.Node.ToModel()
})
}

func (r ReadDLPPolicies) IsEmpty() bool {
return len(r.DLPPolicies.Edges) == 0
}
32 changes: 32 additions & 0 deletions twingate/internal/client/query/dlp-policy-read.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package query

import (
"github.com/Twingate/terraform-provider-twingate/v3/twingate/internal/model"
)

type ReadDLPPolicy struct {
DLPPolicy *gqlDLPPolicy `graphql:"dlpPolicy(id: $id, name: $name)"`
}

type gqlDLPPolicy struct {
IDName
}

func (r gqlDLPPolicy) ToModel() *model.DLPPolicy {
return &model.DLPPolicy{
ID: string(r.ID),
Name: r.Name,
}
}

func (r ReadDLPPolicy) ToModel() *model.DLPPolicy {
if r.DLPPolicy == nil {
return nil
}

return r.DLPPolicy.ToModel()
}

func (r ReadDLPPolicy) IsEmpty() bool {
return r.DLPPolicy == nil
}
9 changes: 9 additions & 0 deletions twingate/internal/client/query/resource-access-set.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package query

type SetResourceAccess struct {
OkError `graphql:"resourceAccessSet(resourceId: $id, access: $access)"`
}

func (q SetResourceAccess) IsEmpty() bool {
return false
}
2 changes: 1 addition & 1 deletion twingate/internal/client/query/resource-create.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package query

type CreateResource struct {
ResourceEntityResponse `graphql:"resourceCreate(name: $name, address: $address, remoteNetworkId: $remoteNetworkId, protocols: $protocols, isVisible: $isVisible, isBrowserShortcutEnabled: $isBrowserShortcutEnabled, alias: $alias, securityPolicyId: $securityPolicyId)"`
ResourceEntityResponse `graphql:"resourceCreate(name: $name, address: $address, remoteNetworkId: $remoteNetworkId, protocols: $protocols, isVisible: $isVisible, isBrowserShortcutEnabled: $isBrowserShortcutEnabled, alias: $alias, securityPolicyId: $securityPolicyId, dlpPolicyId: $dlpPolicyId)"`
}

func (q CreateResource) IsEmpty() bool {
Expand Down
Loading
Loading