Skip to content

Commit

Permalink
AUTH-5670 added common_names to access groups to support multiple com…
Browse files Browse the repository at this point in the history
…mon_name policies within the same policy
  • Loading branch information
rkernscloudflaretest committed Apr 4, 2024
1 parent 3d7ce61 commit 76906b7
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 51 deletions.
6 changes: 6 additions & 0 deletions .changelog/3229.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
```release-note:enhancement
resource/cloudflare_access_policy: added support for common_names rule list type to allow for more than one common_name rule in a policy block
```
```release-note:enhancement
resource/cloudflare_access_group: added support for common_names rule list type to allow for more than one common_name rule in a policy block
```
23 changes: 21 additions & 2 deletions internal/sdkv2provider/resource_cloudflare_access_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,11 @@ func BuildAccessGroupCondition(options map[string]interface{}) []interface{} {
group = append(group, cloudflare.AccessGroupDevicePosture{DevicePosture: struct {
ID string `json:"integration_uid"`
}{ID: value.(string)}})

case "common_names":
group = append(group, cloudflare.AccessGroupCertificateCommonName{CommonName: struct {
CommonName string `json:"common_name"`
}{CommonName: value.(string)}})
}
}
}
Expand Down Expand Up @@ -417,6 +422,7 @@ func TransformAccessGroupForSchema(ctx context.Context, accessGroup []interface{
authCtxID := ""
authCtxIDPID := ""
authCtxACID := ""
commonNames := []string{}

for _, group := range accessGroup {
for groupKey, groupValue := range group.(map[string]interface{}) {
Expand Down Expand Up @@ -448,8 +454,17 @@ func TransformAccessGroupForSchema(ctx context.Context, accessGroup []interface{
serviceTokens = append(serviceTokens, serviceToken.(string))
}
case "common_name":
for _, name := range groupValue.(map[string]interface{}) {
commonName = name.(string)
// if this isn't empty then we know we have multiple common name rules and need to move them to common_names
if commonName != "" {
commonNames = []string{commonName}
commonName = ""
for _, name := range groupValue.(map[string]interface{}) {
commonNames = append(commonNames, name.(string))
}
} else {
for _, name := range groupValue.(map[string]interface{}) {
commonName = name.(string)
}
}
case "auth_method":
for _, method := range groupValue.(map[string]interface{}) {
Expand Down Expand Up @@ -641,6 +656,10 @@ func TransformAccessGroupForSchema(ctx context.Context, accessGroup []interface{
groupMap["device_posture"] = devicePostureRuleIDs
}

if len(commonNames) > 0 {
groupMap["common_names"] = commonNames
}

data = append(data, groupMap)

return data
Expand Down
110 changes: 61 additions & 49 deletions internal/sdkv2provider/resource_cloudflare_access_group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@ package sdkv2provider
import (
"context"
"fmt"
"log"
"os"
"testing"

cloudflare "github.com/cloudflare/cloudflare-go"
"github.com/cloudflare/terraform-provider-cloudflare/internal/consts"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/terraform"
)
Expand All @@ -21,53 +19,6 @@ func init() {
})
}

func testSweepCloudflareAccessGroups(r string) error {
ctx := context.Background()

client, clientErr := sharedClient()
if clientErr != nil {
tflog.Error(ctx, fmt.Sprintf("Failed to create Cloudflare client: %s", clientErr))
}

// Zone level Access Groups
zoneID := os.Getenv("CLOUDFLARE_ZONE_ID")
zoneAccessGroups, _, err := client.ListAccessGroups(context.Background(), cloudflare.ZoneIdentifier(zoneID), cloudflare.ListAccessGroupsParams{})
if err != nil {
tflog.Error(ctx, fmt.Sprintf("Failed to fetch zone level Access Groups: %s", err))
}

if len(zoneAccessGroups) == 0 {
log.Print("[DEBUG] No Cloudflare zone level Access Groups to sweep")
return nil
}

for _, accessGroup := range zoneAccessGroups {
if err := client.DeleteAccessGroup(context.Background(), cloudflare.ZoneIdentifier(zoneID), accessGroup.ID); err != nil {
tflog.Error(ctx, fmt.Sprintf("Failed to delete zone level Access Group %s", accessGroup.ID))
}
}

// Account level Access Groups
accountID := os.Getenv("CLOUDFLARE_ACCOUNT_ID")
accountAccessGroups, _, err := client.ListAccessGroups(context.Background(), cloudflare.AccountIdentifier(accountID), cloudflare.ListAccessGroupsParams{})
if err != nil {
tflog.Error(ctx, fmt.Sprintf("Failed to fetch account level Access Groups: %s", err))
}

if len(accountAccessGroups) == 0 {
log.Print("[DEBUG] No Cloudflare account level Access Groups to sweep")
return nil
}

for _, accessGroup := range accountAccessGroups {
if err := client.DeleteAccessGroup(context.Background(), cloudflare.AccountIdentifier(accountID), accessGroup.ID); err != nil {
tflog.Error(ctx, fmt.Sprintf("Failed to delete account level Access Group %s", accessGroup.ID))
}
}

return nil
}

var (
accountID = os.Getenv("CLOUDFLARE_ACCOUNT_ID")
email = "test@example.com"
Expand Down Expand Up @@ -257,6 +208,9 @@ func TestAccCloudflareAccessGroup_FullConfig(t *testing.T) {
resource.TestCheckResourceAttr(name, "include.0.email_domain.0", "example.com"),
resource.TestCheckResourceAttr(name, "exclude.0.email.0", email),
resource.TestCheckResourceAttr(name, "require.0.email.0", email),
resource.TestCheckResourceAttr(name, "include.0.common_names.0", "common"),
resource.TestCheckResourceAttr(name, "include.0.common_names.1", "name"),
resource.TestCheckNoResourceAttr(name, "include.0.common_name.0"),
),
},
},
Expand Down Expand Up @@ -389,6 +343,39 @@ func TestAccCloudflareAccessGroup_CreateAfterManualDestroy(t *testing.T) {
})
}

func TestAccCloudflareAccessGroup_UpdatedFromCommonNameToCommonNames(t *testing.T) {
var before, after cloudflare.AccessGroup
rnd := generateRandomResourceName()
name := fmt.Sprintf("cloudflare_access_group.%s", rnd)

resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
testAccPreCheckAccount(t)
},
ProviderFactories: providerFactories,
CheckDestroy: testAccCheckCloudflareAccessGroupDestroy,
Steps: []resource.TestStep{
{
Config: testAccCloudflareAccessGroupConfigBasicWithCommonName(rnd, cloudflare.AccountIdentifier(accountID)),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudflareAccessGroupExists(name, cloudflare.AccountIdentifier(accountID), &before),
),
},
{
Config: testAccCloudflareAccessGroupConfigBasicWithCommonNames(rnd, cloudflare.AccountIdentifier(accountID)),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudflareAccessGroupExists(name, cloudflare.AccountIdentifier(accountID), &after),
testAccCheckCloudflareAccessGroupIDUnchanged(&before, &after),
resource.TestCheckResourceAttr(name, "common_names.0", "common"),
resource.TestCheckResourceAttr(name, "common_names.1", "name"),
resource.TestCheckNoResourceAttr(name, "common_name.0"),
),
},
},
})
}

func testAccCloudflareAccessGroupConfigBasic(resourceName string, email string, identifier *cloudflare.ResourceContainer) string {
return fmt.Sprintf(`
resource "cloudflare_access_group" "%[1]s" {
Expand Down Expand Up @@ -483,6 +470,7 @@ resource "cloudflare_access_group" "%[1]s" {
include {
email = ["%[3]s"]
email_domain = ["example.com"]
common_names = ["common", "name"]
}
require {
Expand Down Expand Up @@ -552,6 +540,30 @@ resource "cloudflare_access_group" "%[2]s" {
}`, accountID, rnd, authCtxID, authCtxACID)
}

func testAccCloudflareAccessGroupConfigBasicWithCommonName(resourceName string, identifier *cloudflare.ResourceContainer) string {
return fmt.Sprintf(`
resource "cloudflare_access_group" "%[1]s" {
%[2]s_id = "%[3]s"
name = "%[1]s"
include {
common_name = "common"
}
}`, resourceName, identifier.Type, identifier.Identifier)
}

func testAccCloudflareAccessGroupConfigBasicWithCommonNames(resourceName string, identifier *cloudflare.ResourceContainer) string {
return fmt.Sprintf(`
resource "cloudflare_access_group" "%[1]s" {
%[2]s_id = "%[3]s"
name = "%[1]s"
include {
common_names = ["common", "name"]
}
}`, resourceName, identifier.Type, identifier.Identifier)
}

func testAccCheckCloudflareAccessGroupExists(n string, accessIdentifier *cloudflare.ResourceContainer, accessGroup *cloudflare.AccessGroup) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
Expand Down
8 changes: 8 additions & 0 deletions internal/sdkv2provider/schema_cloudflare_access_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,5 +277,13 @@ var AccessGroupOptionSchemaElement = &schema.Resource{
},
},
},
"common_names": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Description: "Overflow field if you need to have multiple common_name rules in a single policy. Use in place of the singular common_name field.",
},
},
}

0 comments on commit 76906b7

Please sign in to comment.