Skip to content

Commit

Permalink
DLP-1714: added ContextAwareness support for DLP Profiles
Browse files Browse the repository at this point in the history
  • Loading branch information
MattDavis00 committed Mar 14, 2024
1 parent e451cb5 commit e35a621
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .changelog/3158.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/cloudflare_dlp_profile: Added support for `context_awareness` field to profiles
```
18 changes: 18 additions & 0 deletions docs/resources/dlp_profile.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ resource "cloudflare_dlp_profile" "example_custom" {

### Optional

- `context_awareness` (Block List, Max: 1) Scan the context of predefined entries to only return matches surrounded by keywords. (see [below for nested schema](#nestedblock--context_awareness))
- `description` (String) Brief summary of the profile and its intended use.

### Read-Only
Expand Down Expand Up @@ -120,6 +121,23 @@ Optional:

- `validation` (String) The validation algorithm to apply with this pattern.



<a id="nestedblock--context_awareness"></a>
### Nested Schema for `context_awareness`

Required:

- `enabled` (Boolean) Scan the context of predefined entries to only return matches surrounded by keywords.
- `skip` (Block List, Min: 1, Max: 1) Content types to exclude from context analysis and return all matches. (see [below for nested schema](#nestedblock--context_awareness--skip))

<a id="nestedblock--context_awareness--skip"></a>
### Nested Schema for `context_awareness.skip`

Required:

- `files` (Boolean) Return all matches, regardless of context analysis result, if the data is a file.

## Import

Import is supported using the following syntax:
Expand Down
44 changes: 44 additions & 0 deletions internal/sdkv2provider/resource_cloudflare_dlp_profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,38 @@ func dlpEntryToSchema(entry cloudflare.DLPEntry) map[string]interface{} {
return entrySchema
}

func dlpContextAwarenessSkipToAPI(skipSchema map[string]interface{}) cloudflare.DLPContextAwarenessSkip {
files := skipSchema["files"].(bool)
skip := cloudflare.DLPContextAwarenessSkip{
Files: &files,
}
return skip
}

func dlpContextAwarenessToAPI(contextSchema map[string]interface{}) cloudflare.DLPContextAwareness {
enabled := contextSchema["enabled"].(bool)
skip_items := contextSchema["skip"].([]interface{})
skip_item := skip_items[0].(map[string]interface{})
context := cloudflare.DLPContextAwareness{
Enabled: &enabled,
Skip: dlpContextAwarenessSkipToAPI(skip_item),
}
return context
}

func dlpContextAwarenessSkipToSchema(skip cloudflare.DLPContextAwarenessSkip) map[string]interface{} {
skipSchema := make(map[string]interface{})
skipSchema["files"] = skip.Files
return skipSchema
}

func dlpContextAwarenessToSchema(context cloudflare.DLPContextAwareness) map[string]interface{} {
contextSchema := make(map[string]interface{})
contextSchema["enabled"] = *context.Enabled
contextSchema["skip"] = []interface{}{dlpContextAwarenessSkipToSchema(context.Skip)}
return contextSchema
}

func dlpEntryToAPI(entryType string, entryMap map[string]interface{}) cloudflare.DLPEntry {
apiEntry := cloudflare.DLPEntry{
Name: entryMap["name"].(string),
Expand Down Expand Up @@ -109,6 +141,9 @@ func resourceCloudflareDLPProfileRead(ctx context.Context, d *schema.ResourceDat
d.Set("description", dlpProfile.Description)
}
d.Set("allowed_match_count", dlpProfile.AllowedMatchCount)
if dlpProfile.ContextAwareness != nil {
d.Set("context_awareness", []interface{}{dlpContextAwarenessToSchema(*dlpProfile.ContextAwareness)})
}
entries := make([]interface{}, 0, len(dlpProfile.Entries))
for _, entry := range dlpProfile.Entries {
entries = append(entries, dlpEntryToSchema(entry))
Expand All @@ -129,6 +164,11 @@ func resourceCloudflareDLPProfileCreate(ctx context.Context, d *schema.ResourceD
AllowedMatchCount: d.Get("allowed_match_count").(int),
}

if contextAwarenessSchema, ok := d.GetOk("context_awareness.0"); ok {
contextAwareness := dlpContextAwarenessToAPI(contextAwarenessSchema.(map[string]interface{}))
newDLPProfile.ContextAwareness = &contextAwareness
}

if newDLPProfile.Type == DLPProfileTypePredefined {
return diag.FromErr(fmt.Errorf("predefined DLP profiles cannot be created and must be imported"))
}
Expand Down Expand Up @@ -164,6 +204,10 @@ func resourceCloudflareDLPProfileUpdate(ctx context.Context, d *schema.ResourceD
AllowedMatchCount: d.Get("allowed_match_count").(int),
}
updatedDLPProfile.Description, _ = d.Get("description").(string)
if contextAwarenessSchema, ok := d.GetOk("context_awareness.0"); ok {
contextAwareness := dlpContextAwarenessToAPI(contextAwarenessSchema.(map[string]interface{}))
updatedDLPProfile.ContextAwareness = &contextAwareness
}
if entries, ok := d.GetOk("entry"); ok {
for _, entry := range entries.(*schema.Set).List() {
updatedDLPProfile.Entries = append(updatedDLPProfile.Entries, dlpEntryToAPI(updatedDLPProfile.Type, entry.(map[string]interface{})))
Expand Down
66 changes: 66 additions & 0 deletions internal/sdkv2provider/resource_cloudflare_dlp_profile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"fmt"
"testing"

"github.com/cloudflare/cloudflare-go"

"github.com/cloudflare/terraform-provider-cloudflare/internal/consts"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/plancheck"
Expand Down Expand Up @@ -105,6 +107,44 @@ func TestAccCloudflareDLPProfile_CustomWithAllowedMatchCount(t *testing.T) {
})
}

func TestAccCloudflareDLPProfile_ContextAwareness(t *testing.T) {
rnd := generateRandomResourceName()
name := fmt.Sprintf("cloudflare_dlp_profile.%s", rnd)

enabled := true
files := true

resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheckAccount(t)
},
ProviderFactories: providerFactories,
Steps: []resource.TestStep{
{
Config: testAccCloudflareDLPProfileConfigWithContextAwareness(accountID, rnd, "custom profile", cloudflare.DLPContextAwareness{
Enabled: &enabled,
Skip: cloudflare.DLPContextAwarenessSkip{
Files: &files,
},
}),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(name, consts.AccountIDSchemaKey, accountID),
resource.TestCheckResourceAttr(name, "name", rnd),
resource.TestCheckResourceAttr(name, "description", "custom profile"),
resource.TestCheckResourceAttr(name, "type", "custom"),
resource.TestCheckResourceAttr(name, "allowed_match_count", "0"),
resource.TestCheckResourceAttr(name, "entry.0.name", fmt.Sprintf("%s_entry1", rnd)),
resource.TestCheckResourceAttr(name, "entry.0.enabled", "true"),
resource.TestCheckResourceAttr(name, "entry.0.pattern.0.regex", "^4[0-9]"),
resource.TestCheckResourceAttr(name, "entry.0.pattern.0.validation", "luhn"),
resource.TestCheckResourceAttr(name, "context_awareness.0.enabled", "true"),
resource.TestCheckResourceAttr(name, "context_awareness.0.skip.0.files", "true"),
),
},
},
})
}

func testAccCloudflareDLPProfileConfigCustom(accountID, rnd, description string) string {
return fmt.Sprintf(`
resource "cloudflare_dlp_profile" "%[1]s" {
Expand Down Expand Up @@ -172,3 +212,29 @@ resource "cloudflare_dlp_profile" "%[1]s" {
}
`, rnd, description, accountID, allowedMatchCount)
}

func testAccCloudflareDLPProfileConfigWithContextAwareness(accountID, rnd, description string, contextAwareness cloudflare.DLPContextAwareness) string {
return fmt.Sprintf(`
resource "cloudflare_dlp_profile" "%[2]s" {
account_id = "%[1]s"
name = "%[2]s"
description = "%[3]s"
allowed_match_count = 0
type = "custom"
entry {
name = "%[2]s_entry1"
enabled = true
pattern {
regex = "^4[0-9]"
validation = "luhn"
}
}
context_awareness {
enabled = %[4]t
skip {
files = %[5]t
}
}
}
`, accountID, rnd, description, *contextAwareness.Enabled, *contextAwareness.Skip.Files)
}
35 changes: 35 additions & 0 deletions internal/sdkv2provider/schema_cloudflare_dlp_profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,31 @@ func hashResourceCloudflareDLPEntry(i interface{}) int {
return schema.HashString(v["name"])
}

func resourceCloudflareDLPContextAwarenessSchema() map[string]*schema.Schema {
return map[string]*schema.Schema{
"enabled": {
Type: schema.TypeBool,
Required: true,
Description: "Scan the context of predefined entries to only return matches surrounded by keywords.",
},
"skip": {
Type: schema.TypeList,
Description: "Content types to exclude from context analysis and return all matches.",
Required: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"files": {
Type: schema.TypeBool,
Required: true,
Description: "Return all matches, regardless of context analysis result, if the data is a file.",
},
},
},
},
}
}

func resourceCloudflareDLPProfileSchema() map[string]*schema.Schema {
return map[string]*schema.Schema{
consts.AccountIDSchemaKey: {
Expand Down Expand Up @@ -107,5 +132,15 @@ func resourceCloudflareDLPProfileSchema() map[string]*schema.Schema {
Required: true,
ValidateFunc: validation.IntBetween(0, 1000),
},
"context_awareness": {
Type: schema.TypeList,
Description: "Scan the context of predefined entries to only return matches surrounded by keywords.",
Computed: true,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: resourceCloudflareDLPContextAwarenessSchema(),
},
},
}
}

0 comments on commit e35a621

Please sign in to comment.