Skip to content

Commit

Permalink
Add teams list and device posture rule resources
Browse files Browse the repository at this point in the history
  • Loading branch information
Justin-Holmes committed May 21, 2021
1 parent 5d39f78 commit 5b0f375
Show file tree
Hide file tree
Showing 9 changed files with 762 additions and 0 deletions.
2 changes: 2 additions & 0 deletions cloudflare/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ func Provider() terraform.ResourceProvider {
"cloudflare_custom_hostname_fallback_origin": resourceCloudflareCustomHostnameFallbackOrigin(),
"cloudflare_custom_pages": resourceCloudflareCustomPages(),
"cloudflare_custom_ssl": resourceCloudflareCustomSsl(),
"cloudflare_device_posture_rule": resourceCloudflareDevicePostureRule(),
"cloudflare_filter": resourceCloudflareFilter(),
"cloudflare_firewall_rule": resourceCloudflareFirewallRule(),
"cloudflare_healthcheck": resourceCloudflareHealthcheck(),
Expand All @@ -140,6 +141,7 @@ func Provider() terraform.ResourceProvider {
"cloudflare_rate_limit": resourceCloudflareRateLimit(),
"cloudflare_record": resourceCloudflareRecord(),
"cloudflare_spectrum_application": resourceCloudflareSpectrumApplication(),
"cloudflare_teams_list": resourceCloudflareTeamsList(),
"cloudflare_waf_group": resourceCloudflareWAFGroup(),
"cloudflare_waf_package": resourceCloudflareWAFPackage(),
"cloudflare_waf_rule": resourceCloudflareWAFRule(),
Expand Down
22 changes: 22 additions & 0 deletions cloudflare/resource_cloudflare_access_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,13 @@ var AccessGroupOptionSchemaElement = &schema.Resource{
Type: schema.TypeString,
},
},
"device_posture": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"gsuite": {
Type: schema.TypeList,
Optional: true,
Expand Down Expand Up @@ -533,6 +540,10 @@ func BuildAccessGroupCondition(options map[string]interface{}) []interface{} {
group = append(group, cloudflare.AccessGroupLoginMethod{LoginMethod: struct {
ID string `json:"id"`
}{ID: value.(string)}})
case "device_posture":
group = append(group, cloudflare.AccessGroupDevicePosture{DevicePosture: struct {
ID string `json:"integration_uid"`
}{ID: value.(string)}})
}
}
}
Expand Down Expand Up @@ -564,6 +575,7 @@ func TransformAccessGroupForSchema(accessGroup []interface{}) []map[string]inter
azureIDs := []string{}
samlAttrName := ""
samlAttrValue := ""
devicePostureRuleIDs := []string{}

for _, group := range accessGroup {
for groupKey, groupValue := range group.(map[string]interface{}) {
Expand Down Expand Up @@ -625,6 +637,10 @@ func TransformAccessGroupForSchema(accessGroup []interface{}) []map[string]inter
for _, group := range groupValue.(map[string]interface{}) {
groups = append(groups, group.(string))
}
case "device_posture":
for _, dprID := range groupValue.(map[string]interface{}) {
devicePostureRuleIDs = append(devicePostureRuleIDs, dprID.(string))
}
default:
log.Printf("[DEBUG] Access Group key %q not transformed", groupKey)
}
Expand Down Expand Up @@ -730,5 +746,11 @@ func TransformAccessGroupForSchema(accessGroup []interface{}) []map[string]inter
})
}

if len(devicePostureRuleIDs) > 0 {
data = append(data, map[string]interface{}{
"device_posture": devicePostureRuleIDs,
})
}

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

import (
"context"
"encoding/json"
"fmt"
"log"
"strings"

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

func resourceCloudflareDevicePostureRule() *schema.Resource {
return &schema.Resource{
Create: resourceCloudflareDevicePostureRuleCreate,
Read: resourceCloudflareDevicePostureRuleRead,
Update: resourceCloudflareDevicePostureRuleUpdate,
Delete: resourceCloudflareDevicePostureRuleDelete,
Importer: &schema.ResourceImporter{
State: resourceCloudflareDevicePostureRuleImport,
},

Schema: map[string]*schema.Schema{
"account_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"type": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"serial_number", "file", "application"}, false),
},
"name": {
Type: schema.TypeString,
Optional: true,
},
"description": {
Type: schema.TypeString,
Optional: true,
},
"schedule": {
Type: schema.TypeString,
Optional: true,
},
"match": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"platform": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{"windows", "mac", "linux", "android", "ios"}, false),
},
},
},
},
"input": {
Type: schema.TypeList,
Required: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"id": {
Type: schema.TypeString,
Optional: true,
},
"path": {
Type: schema.TypeString,
Optional: true,
},
"exists": {
Type: schema.TypeBool,
Optional: true,
},
"thumbprint": {
Type: schema.TypeString,
Optional: true,
},
"sha256": {
Type: schema.TypeString,
Optional: true,
},
"running": {
Type: schema.TypeBool,
Optional: true,
},
},
},
},
},
}
}

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

newDevicePostureRule := cloudflare.DevicePostureRule{
Name: d.Get("name").(string),
Type: d.Get("type").(string),
Description: d.Get("description").(string),
Schedule: d.Get("schedule").(string),
}

err := setDevicePostureRuleMatch(&newDevicePostureRule, d)
if err != nil {
return fmt.Errorf("error creating Device Posture Rule with provided match input: %s", err)
}

setDevicePostureRuleInput(&newDevicePostureRule, d)

log.Printf("[DEBUG] Creating Cloudflare Device Posture Rule from struct: %+v", newDevicePostureRule)

rule, err := client.CreateDevicePostureRule(context.Background(), accountID, newDevicePostureRule)
if err != nil {
return fmt.Errorf("error creating Device Posture Rule for account %q: %s", accountID, err)
}

d.SetId(rule.ID)

return resourceCloudflareDevicePostureRuleRead(d, meta)
}

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

devicePostureRule, err := client.DevicePostureRule(context.Background(), accountID, d.Id())
if err != nil {
if strings.Contains(err.Error(), "HTTP status 404") {
log.Printf("[INFO] Device Posture Rule %s no longer exists", d.Id())
d.SetId("")
return nil
}
return fmt.Errorf("Error finding Device Posture Rule %q: %s", d.Id(), err)
}

d.Set("name", devicePostureRule.Name)
d.Set("description", devicePostureRule.Description)
d.Set("type", devicePostureRule.Type)
d.Set("schedule", devicePostureRule.Schedule)
d.Set("match", devicePostureRule.Match)
d.Set("input", devicePostureRule.Input)

return nil
}

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

updatedDevicePostureRule := cloudflare.DevicePostureRule{
ID: d.Id(),
Name: d.Get("name").(string),
Type: d.Get("type").(string),
Description: d.Get("description").(string),
Schedule: d.Get("schedule").(string),
}

err := setDevicePostureRuleMatch(&updatedDevicePostureRule, d)
if err != nil {
return fmt.Errorf("error creating Device Posture Rule with provided match input: %s", err)
}

setDevicePostureRuleInput(&updatedDevicePostureRule, d)

log.Printf("[DEBUG] Updating Cloudflare Device Posture Rule from struct: %+v", updatedDevicePostureRule)

devicePostureRule, err := client.UpdateDevicePostureRule(context.Background(), accountID, updatedDevicePostureRule)
if err != nil {
return fmt.Errorf("error updating Device Posture Rule for account %q: %s", accountID, err)
}

if devicePostureRule.ID == "" {
return fmt.Errorf("failed to find Device Posture Rule ID in update response; resource was empty")
}

return resourceCloudflareDevicePostureRuleRead(d, meta)
}

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

log.Printf("[DEBUG] Deleting Cloudflare Device Posture Rule using ID: %s", appID)

err := client.DeleteDevicePostureRule(context.Background(), accountID, appID)
if err != nil {
return fmt.Errorf("error deleting Device Posture Rule for account %q: %s", accountID, err)
}

resourceCloudflareDevicePostureRuleRead(d, meta)

return nil
}

func resourceCloudflareDevicePostureRuleImport(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/devicePostureRuleID\"", d.Id())
}

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

log.Printf("[DEBUG] Importing Cloudflare Device Posture Rule: id %s for account %s", devicePostureRuleID, accountID)

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

resourceCloudflareDevicePostureRuleRead(d, meta)

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

func setDevicePostureRuleInput(rule *cloudflare.DevicePostureRule, d *schema.ResourceData) {
if _, ok := d.GetOk("input"); ok {
input := cloudflare.DevicePostureRuleInput{}
if inputID, ok := d.GetOk("input.0.id"); ok {
input.ID = inputID.(string)
}
if p, ok := d.GetOk("input.0.path"); ok {
input.Path = p.(string)
}
if exists, ok := d.GetOk("input.0.exists"); ok {
input.Exists = exists.(bool)
}
if tp, ok := d.GetOk("input.0.thumbprint"); ok {
input.Thumbprint = tp.(string)
}
if s, ok := d.GetOk("input.0.sha256"); ok {
input.Sha256 = s.(string)
}
if running, ok := d.GetOk("input.0.running"); ok {
input.Running = running.(bool)
}

rule.Input = input
}
}

func setDevicePostureRuleMatch(rule *cloudflare.DevicePostureRule, d *schema.ResourceData) error {
if _, ok := d.GetOk("match"); ok {
match := d.Get("match").([]interface{})
for _, v := range match {
jsonString, err := json.Marshal(v.(map[string]interface{}))
if err != nil {
return err
}

var dprMatch cloudflare.DevicePostureRuleMatch
err = json.Unmarshal(jsonString, &dprMatch)
if err != nil {
return err
}

rule.Match = append(rule.Match, dprMatch)
}
}

return nil
}
Loading

0 comments on commit 5b0f375

Please sign in to comment.