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 security policy to resource #31

Closed
wants to merge 16 commits into from
Closed
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
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ jobs:
name: Matrix Acceptance Tests
needs: build
runs-on: ubuntu-latest
if: "!github.event.pull_request.head.repo.fork"
# if: "!github.event.pull_request.head.repo.fork"
timeout-minutes: 15
strategy:
fail-fast: false
Expand Down Expand Up @@ -169,7 +169,7 @@ jobs:

cleanup:
name: Cleanup
if: "!github.event.pull_request.head.repo.fork"
# if: "!github.event.pull_request.head.repo.fork"
needs: tests-acceptance
runs-on: ubuntu-latest
timeout-minutes: 15
Expand Down
2 changes: 2 additions & 0 deletions docs/resources/resource.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ resource "twingate_resource" "resource" {
- `is_browser_shortcut_enabled` (Boolean) Controls whether an "Open in Browser" shortcut will be shown for this Resource in the Twingate Client.
- `is_visible` (Boolean) Controls whether this Resource will be visible in the main Resource list in the Twingate Client.
- `protocols` (Block List, Max: 1) Restrict access to certain protocols and ports. By default or when this argument is not defined, there is no restriction, and all protocols and ports are allowed. (see [below for nested schema](#nestedblock--protocols))
- `security_policy_id` (String) The ID of a twingate_security_policy to set as this Resource's Security Policy.

### Read-Only

Expand All @@ -81,6 +82,7 @@ resource "twingate_resource" "resource" {
Optional:

- `group_ids` (Set of String) List of Group IDs 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.
- `service_account_ids` (Set of String) List of Service Account IDs that will have permission to access the Resource.


Expand Down
1 change: 1 addition & 0 deletions golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ linters-settings:
- github.com/hashicorp/terraform-plugin-framework/datasource.DataSource
- github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier.Set
- github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier.Bool
- github.com/hashicorp/terraform-plugin-framework/attr.Value
errcheck:
check-type-assertions: false
check-blank: false
Expand Down
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, groupIds: $groupIds, protocols: $protocols, isVisible: $isVisible, isBrowserShortcutEnabled: $isBrowserShortcutEnabled, alias: $alias)"`
ResourceEntityResponse `graphql:"resourceCreate(name: $name, address: $address, remoteNetworkId: $remoteNetworkId, protocols: $protocols, isVisible: $isVisible, isBrowserShortcutEnabled: $isBrowserShortcutEnabled, alias: $alias, securityPolicyId: $securityPolicyId)"`
}

func (q CreateResource) IsEmpty() bool {
Expand Down
16 changes: 15 additions & 1 deletion twingate/internal/client/query/resource-read.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ type Access struct {
}

type AccessEdge struct {
Node Principal
Node Principal
SecurityPolicy *gqlSecurityPolicy
}

type Principal struct {
Expand All @@ -56,6 +57,7 @@ type ResourceNode struct {
IsVisible bool
IsBrowserShortcutEnabled bool
Alias string
SecurityPolicy *gqlSecurityPolicy
}

type Protocols struct {
Expand All @@ -81,6 +83,12 @@ func (r gqlResource) ToModel() *model.Resource {
switch access.Node.Type {
case AccessGroup:
resource.Groups = append(resource.Groups, string(access.Node.ID))

if resource.GroupsSecurityPolicyID == nil && access.SecurityPolicy != nil {
id := string(access.SecurityPolicy.ID)
resource.GroupsSecurityPolicyID = &id
}

case AccessServiceAccount:
resource.ServiceAccounts = append(resource.ServiceAccounts, string(access.Node.ID))
}
Expand All @@ -90,6 +98,11 @@ func (r gqlResource) ToModel() *model.Resource {
}

func (r ResourceNode) ToModel() *model.Resource {
var securityPolicyID string
if r.SecurityPolicy != nil {
securityPolicyID = string(r.SecurityPolicy.ID)
}

return &model.Resource{
ID: string(r.ID),
Name: r.Name,
Expand All @@ -100,6 +113,7 @@ func (r ResourceNode) ToModel() *model.Resource {
IsVisible: &r.IsVisible,
IsBrowserShortcutEnabled: &r.IsBrowserShortcutEnabled,
Alias: optionalString(r.Alias),
SecurityPolicyID: optionalString(securityPolicyID),
}
}

Expand Down
2 changes: 1 addition & 1 deletion twingate/internal/client/query/resource-update.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package query

type UpdateResource struct {
ResourceEntityResponse `graphql:"resourceUpdate(id: $id, name: $name, address: $address, remoteNetworkId: $remoteNetworkId, protocols: $protocols, isVisible: $isVisible, isBrowserShortcutEnabled: $isBrowserShortcutEnabled, alias: $alias)"`
ResourceEntityResponse `graphql:"resourceUpdate(id: $id, name: $name, address: $address, remoteNetworkId: $remoteNetworkId, protocols: $protocols, isVisible: $isVisible, isBrowserShortcutEnabled: $isBrowserShortcutEnabled, alias: $alias, securityPolicyId: $securityPolicyId)"`
}

func (q UpdateResource) IsEmpty() bool {
Expand Down
9 changes: 6 additions & 3 deletions twingate/internal/client/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,13 @@ func (client *Client) CreateResource(ctx context.Context, input *model.Resource)

variables := newVars(
gqlID(input.RemoteNetworkID, "remoteNetworkId"),
gqlIDs(input.Groups, "groupIds"),
gqlVar(input.Name, "name"),
gqlVar(input.Address, "address"),
gqlVar(newProtocolsInput(input.Protocols), "protocols"),
gqlNullable(input.IsVisible, "isVisible"),
gqlNullable(input.IsBrowserShortcutEnabled, "isBrowserShortcutEnabled"),
gqlNullable(input.Alias, "alias"),
gqlNullableID(input.SecurityPolicyID, "securityPolicyId"),
cursor(query.CursorAccess),
pageLimit(client.pageLimit),
)
Expand All @@ -81,8 +81,10 @@ func (client *Client) CreateResource(ctx context.Context, input *model.Resource)

resource := response.Entity.ToModel()
resource.Groups = input.Groups
resource.GroupsSecurityPolicyID = input.GroupsSecurityPolicyID
resource.ServiceAccounts = input.ServiceAccounts
resource.IsAuthoritative = input.IsAuthoritative
resource.SecurityPolicyID = input.SecurityPolicyID

if input.IsVisible == nil {
resource.IsVisible = nil
Expand Down Expand Up @@ -180,6 +182,7 @@ func (client *Client) UpdateResource(ctx context.Context, input *model.Resource)
gqlNullable(input.IsVisible, "isVisible"),
gqlNullable(input.IsBrowserShortcutEnabled, "isBrowserShortcutEnabled"),
gqlNullable(input.Alias, "alias"),
gqlNullableID(input.SecurityPolicyID, "securityPolicyId"),
cursor(query.CursorAccess),
pageLimit(client.pageLimit),
)
Expand Down Expand Up @@ -292,7 +295,7 @@ type AccessInput struct {
SecurityPolicyID *string `json:"securityPolicyId"`
}

func (client *Client) AddResourceAccess(ctx context.Context, resourceID string, principalIDs []string) error {
func (client *Client) AddResourceAccess(ctx context.Context, resourceID string, principalIDs []string, securityPolicyID *string) error {
opr := resourceResourceAccess.update()

if len(principalIDs) == 0 {
Expand All @@ -304,7 +307,7 @@ func (client *Client) AddResourceAccess(ctx context.Context, resourceID string,
}

access := utils.Map(principalIDs, func(id string) AccessInput {
return AccessInput{PrincipalID: id}
return AccessInput{PrincipalID: id, SecurityPolicyID: securityPolicyID}
})

variables := newVars(
Expand Down
2 changes: 1 addition & 1 deletion twingate/internal/client/variables.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func getValue(val any) any {
}
}

func gqlNullableID(val interface{}, name string) gqlVarOption {
func gqlNullableID(val interface{}, name string) gqlVarOption { //nolint
return func(values map[string]interface{}) map[string]interface{} {
var (
gqlValue interface{}
Expand Down
3 changes: 3 additions & 0 deletions twingate/internal/model/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,15 @@ type Resource struct {
IsVisible *bool
IsBrowserShortcutEnabled *bool
Alias *string
SecurityPolicyID *string
GroupsSecurityPolicyID *string
}

func (r Resource) AccessToTerraform() []interface{} {
rawMap := make(map[string]interface{})
if len(r.Groups) != 0 {
rawMap[attr.GroupIDs] = r.Groups
rawMap[attr.SecurityPolicyID] = r.GroupsSecurityPolicyID
}

if len(r.ServiceAccounts) != 0 {
Expand Down
Loading
Loading