Skip to content

Commit

Permalink
Merge pull request #1517 from Michael9127/mike/GATE-2448-add-proxy-en…
Browse files Browse the repository at this point in the history
…dpoint-support

GATE-2448: Adds support for proxy endpoints
  • Loading branch information
jacobbednarz authored Mar 21, 2022
2 parents 45e1431 + 001bfbf commit df3f6f4
Show file tree
Hide file tree
Showing 8 changed files with 795 additions and 489 deletions.
3 changes: 3 additions & 0 deletions .changelog/1517.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-resource
cloudflare_teams_proxy_endpoint
```
999 changes: 510 additions & 489 deletions CHANGELOG.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions cloudflare/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ func Provider() *schema.Provider {
"cloudflare_teams_list": resourceCloudflareTeamsList(),
"cloudflare_teams_location": resourceCloudflareTeamsLocation(),
"cloudflare_teams_rule": resourceCloudflareTeamsRule(),
"cloudflare_teams_proxy_endpoint": resourceCloudflareTeamsProxyEndpoint(),
"cloudflare_waf_group": resourceCloudflareWAFGroup(),
"cloudflare_waf_override": resourceCloudflareWAFOverride(),
"cloudflare_waf_package": resourceCloudflareWAFPackage(),
Expand Down
132 changes: 132 additions & 0 deletions cloudflare/resource_cloudflare_teams_proxy_endpoints.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package cloudflare

import (
"context"
"fmt"
"log"
"strings"

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

func resourceCloudflareTeamsProxyEndpoint() *schema.Resource {
return &schema.Resource{
Schema: resourceCloudflareTeamsProxyEndpointSchema(),
Create: resourceCloudflareTeamsProxyEndpointCreate,
Read: resourceCloudflareTeamsProxyEndpointRead,
Update: resourceCloudflareTeamsProxyEndpointUpdate,
Delete: resourceCloudflareTeamsProxyEndpointDelete,
Importer: &schema.ResourceImporter{
State: resourceCloudflareTeamsProxyEndpointImport,
},
}
}

func resourceCloudflareTeamsProxyEndpointRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*cloudflare.API)
accountID := d.Get("account_id").(string)

endpoint, err := client.TeamsProxyEndpoint(context.Background(), accountID, d.Id())
if err != nil {
if strings.Contains(err.Error(), "HTTP status 400") {
log.Printf("[INFO] Teams Proxy Endpoint %s no longer exists", d.Id())
d.SetId("")
return nil
}
return fmt.Errorf("error finding Teams Proxy Endpoint %q: %s", d.Id(), err)
}

if err := d.Set("name", endpoint.Name); err != nil {
return fmt.Errorf("error parsing Proxy Endpoint name")
}

if err := d.Set("ips", endpoint.IPs); err != nil {
return fmt.Errorf("error parsing Proxy Endpoint IPs")
}

if err := d.Set("subdomain", endpoint.Subdomain); err != nil {
return fmt.Errorf("error parsing Proxy Endpoint subdomain")
}

return nil
}

func resourceCloudflareTeamsProxyEndpointCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*cloudflare.API)

accountID := d.Get("account_id").(string)
newProxyEndpoint := cloudflare.TeamsProxyEndpoint{
Name: d.Get("name").(string),
IPs: expandInterfaceToStringList(d.Get("ips").(*schema.Set).List()),
}

log.Printf("[DEBUG] Creating Cloudflare Teams Proxy Endpoint from struct: %+v", newProxyEndpoint)

proxyEndpoint, err := client.CreateTeamsProxyEndpoint(context.Background(), accountID, newProxyEndpoint)
if err != nil {
return fmt.Errorf("error creating Teams Proxy Endpoint for account %q: %s", accountID, err)
}

d.SetId(proxyEndpoint.ID)
return resourceCloudflareTeamsProxyEndpointRead(d, meta)

}

func resourceCloudflareTeamsProxyEndpointUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*cloudflare.API)
accountID := d.Get("account_id").(string)
updatedProxyEndpoint := cloudflare.TeamsProxyEndpoint{
ID: d.Id(),
Name: d.Get("name").(string),
IPs: expandInterfaceToStringList(d.Get("ips").(*schema.Set).List()),
}

log.Printf("[DEBUG] Updating Cloudflare Teams Proxy Endpoint from struct: %+v", updatedProxyEndpoint)

teamsProxyEndpoint, err := client.UpdateTeamsProxyEndpoint(context.Background(), accountID, updatedProxyEndpoint)

if err != nil {
return fmt.Errorf("error updating Teams Proxy Endpoint for account %q: %s", accountID, err)
}

if teamsProxyEndpoint.ID == "" {
return fmt.Errorf("failed to find Teams Proxy Endpoint ID in update response; resource was empty")
}
return resourceCloudflareTeamsProxyEndpointRead(d, meta)
}

func resourceCloudflareTeamsProxyEndpointDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*cloudflare.API)
id := d.Id()
accountID := d.Get("account_id").(string)

log.Printf("[DEBUG] Deleting Cloudflare Teams Proxy Endpoint using ID: %s", id)

err := client.DeleteTeamsProxyEndpoint(context.Background(), accountID, id)
if err != nil {
return fmt.Errorf("error deleting Teams Proxy Endpoint for account %q: %s", accountID, err)
}

return resourceCloudflareTeamsProxyEndpointRead(d, meta)
}

func resourceCloudflareTeamsProxyEndpointImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
attributes := strings.SplitN(d.Id(), "/", 2)

if len(attributes) != 2 {
return nil, fmt.Errorf("invalid id (\"%s\") specified, should be in format \"accountID/teamsProxyEndpointID\"", d.Id())
}

accountID, teamsProxyEndpointID := attributes[0], attributes[1]

log.Printf("[DEBUG] Importing Cloudflare Teams Proxy Endpoint: id %s for account %s", teamsProxyEndpointID, accountID)

d.Set("account_id", accountID)
d.SetId(teamsProxyEndpointID)

err := resourceCloudflareTeamsProxyEndpointRead(d, meta)

return []*schema.ResourceData{d}, err

}
74 changes: 74 additions & 0 deletions cloudflare/resource_cloudflare_teams_proxy_endpoints_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package cloudflare

import (
"context"
"fmt"
"os"
"regexp"
"testing"

"github.com/cloudflare/cloudflare-go"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)

func TestAccCloudflareTeamsProxyEndpoint_Basic(t *testing.T) {
// Temporarily unset CLOUDFLARE_API_TOKEN if it is set as the Access
// service does not yet support the API tokens and it results in
// misleading state error messages.
if os.Getenv("CLOUDFLARE_API_TOKEN") != "" {
defer func(apiToken string) {
os.Setenv("CLOUDFLARE_API_TOKEN", apiToken)
}(os.Getenv("CLOUDFLARE_API_TOKEN"))
os.Setenv("CLOUDFLARE_API_TOKEN", "")
}

rnd := generateRandomResourceName()
name := fmt.Sprintf("cloudflare_teams_proxy_endpoint.%s", rnd)

resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccessAccPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testAccCheckCloudflareTeamsProxyEndpointDestroy,
Steps: []resource.TestStep{
{
Config: testAccCloudflareTeamsProxyEndpointConfigBasic(rnd, accountID),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(name, "account_id", accountID),
resource.TestCheckResourceAttr(name, "name", rnd),
resource.TestCheckResourceAttr(name, "ips.0", "104.16.132.229/32"),
resource.TestMatchResourceAttr(name, "subdomain", regexp.MustCompile("^[a-zA-Z0-9]+$")),
),
},
},
})
}

func testAccCloudflareTeamsProxyEndpointConfigBasic(rnd, accountID string) string {
return fmt.Sprintf(`
resource "cloudflare_teams_proxy_endpoint" "%[1]s" {
name = "%[1]s"
account_id = "%[2]s"
ips = ["104.16.132.229/32"]
}
`, rnd, accountID)
}

func testAccCheckCloudflareTeamsProxyEndpointDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*cloudflare.API)

for _, rs := range s.RootModule().Resources {
if rs.Type != "cloudflare_teams_proxy_endpoint" {
continue
}

_, err := client.TeamsProxyEndpoint(context.Background(), rs.Primary.Attributes["account_id"], rs.Primary.ID)
if err == nil {
return fmt.Errorf("teams Proxy Endpoint still exists")
}
}

return nil
}
26 changes: 26 additions & 0 deletions cloudflare/schema_cloudflare_teams_proxy_endpoints.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package cloudflare

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

func resourceCloudflareTeamsProxyEndpointSchema() map[string]*schema.Schema {

return map[string]*schema.Schema{
"account_id": {
Type: schema.TypeString,
Required: true,
},
"name": {
Type: schema.TypeString,
Required: true,
},
"subdomain": {
Type: schema.TypeString,
Computed: true,
},
"ips": {
Type: schema.TypeSet,
Elem: &schema.Schema{Type: schema.TypeString},
Required: true,
},
}
}
3 changes: 3 additions & 0 deletions website/cloudflare.erb
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,9 @@
<li<%= sidebar_current("docs-cloudflare-teams-rule") %>>
<a href="/docs/providers/cloudflare/r/teams_rule.html">cloudflare_teams_rule</a>
</li>
<li<%= sidebar_current("docs-cloudflare-teams-proxy-endpoint") %>>
<a href="/docs/providers/cloudflare/r/teams_proxy_endpoint.html">cloudflare_teams_proxy_endpoint</a>
</li>
<li<%= sidebar_current("docs-cloudflare-resource-waf-group") %>>
<a href="/docs/providers/cloudflare/r/waf_group.html">cloudflare_waf_group</a>
</li>
Expand Down
46 changes: 46 additions & 0 deletions website/docs/r/teams_proxy_endpoint.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
---
layout: "cloudflare"
page_title: "Cloudflare: cloudflare_teams_proxy_endpoint"
sidebar_current: "docs-cloudflare-resource-teams-proxy-endpoint"
description: |-
Provides a Cloudflare Teams Proxy Endpoint resource.
---

# cloudflare_teams_proxy_endpoint

Provides a Cloudflare Teams Proxy Endpoint resource. Teams Proxy Endpoints are used for pointing proxy clients at
Cloudflare Secure Gateway.

## Example Usage

```hcl
resource "cloudflare_teams_proxy_endpoint" "corporate_office" {
name = "office"
account_id = "1d5fdc9e88c8a8c4518b068cd94331fe"
ips = ["192.0.2.0/24"]
}
```

## Argument Reference

The following arguments are supported:

* `account_id` - (Required) The account to which the teams proxy endpoint should be added.
* `name` - (Required) Name of the teams proxy endpoint.
* `ips` - (Required) The networks CIDRs that will be allowed to initiate proxy connections.

## Attributes Reference

The following additional attributes are exported:

* `id` - ID of the teams proxy endpoint.
* `subdomain` - The FQDN that proxy clients should be pointed at.

## Import

Teams Proxy Endpoints can be imported using a composite ID formed of account
ID and teams proxy_endpoint ID.

```
$ terraform import cloudflare_teams_proxy_endpoint.corporate_office cb029e245cfdd66dc8d2e570d5dd3322/d41d8cd98f00b204e9800998ecf8427e
```

0 comments on commit df3f6f4

Please sign in to comment.