-
Notifications
You must be signed in to change notification settings - Fork 626
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
simplify resource to be single detection based
- Loading branch information
1 parent
4167c6f
commit 8a4727e
Showing
8 changed files
with
290 additions
and
542 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
8 changes: 2 additions & 6 deletions
8
...ce/leaked_credential_check_rules/model.go → ...ice/leaked_credential_check_rule/model.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
151 changes: 151 additions & 0 deletions
151
internal/framework/service/leaked_credential_check_rule/resource.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
package leaked_credential_check_rule | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/cloudflare/cloudflare-go" | ||
"github.com/cloudflare/terraform-provider-cloudflare/internal/framework/muxclient" | ||
|
||
"github.com/hashicorp/terraform-plugin-framework/path" | ||
"github.com/hashicorp/terraform-plugin-framework/resource" | ||
"github.com/hashicorp/terraform-plugin-framework/types" | ||
) | ||
|
||
var ( | ||
_ resource.Resource = &LeakedCredentialCheckRuleResource{} | ||
_ resource.ResourceWithImportState = &LeakedCredentialCheckRuleResource{} | ||
) | ||
|
||
func NewResource() resource.Resource { | ||
return &LeakedCredentialCheckRuleResource{} | ||
} | ||
|
||
type LeakedCredentialCheckRuleResource struct { | ||
client *muxclient.Client | ||
} | ||
|
||
func (r *LeakedCredentialCheckRuleResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { | ||
resp.TypeName = req.ProviderTypeName + "_leaked_credential_check_rule" | ||
} | ||
|
||
func (r *LeakedCredentialCheckRuleResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { | ||
if req.ProviderData == nil { | ||
return | ||
} | ||
|
||
client, ok := req.ProviderData.(*muxclient.Client) | ||
|
||
if !ok { | ||
resp.Diagnostics.AddError( | ||
"unexpected resource configure type", | ||
fmt.Sprintf("Expected *muxclient.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData), | ||
) | ||
|
||
return | ||
} | ||
|
||
r.client = client | ||
} | ||
|
||
func (r *LeakedCredentialCheckRuleResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { | ||
var data LeakedCredentialCheckRulesModel | ||
diags := req.Plan.Get(ctx, &data) | ||
resp.Diagnostics.Append(diags...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
detection, err := r.client.V1.LeakedCredentialCheckCreateDetection(ctx, cloudflare.ZoneIdentifier(data.ZoneID.ValueString()), cloudflare.LeakedCredentialCheckCreateDetectionParams{ | ||
Username: data.Username.ValueString(), | ||
Password: data.Password.ValueString(), | ||
}) | ||
if err != nil { | ||
resp.Diagnostics.AddError("Error creating a user-defined detection patter for Leaked Credential Check", err.Error()) | ||
return | ||
} | ||
|
||
data.ID = types.StringValue(detection.ID) | ||
|
||
diags = resp.State.Set(ctx, &data) | ||
resp.Diagnostics.Append(diags...) | ||
} | ||
|
||
func (r *LeakedCredentialCheckRuleResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { | ||
var state LeakedCredentialCheckRulesModel | ||
diags := req.State.Get(ctx, &state) | ||
resp.Diagnostics.Append(diags...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
zoneID := state.ZoneID.ValueString() | ||
var foundRule cloudflare.LeakedCredentialCheckDetectionEntry | ||
rules, err := r.client.V1.LeakedCredentialCheckListDetections(ctx, cloudflare.ZoneIdentifier(zoneID), cloudflare.LeakedCredentialCheckListDetectionsParams{}) | ||
if err != nil { | ||
resp.Diagnostics.AddError("Error listing Leaked Credential Check user-defined detection patterns", err.Error()) | ||
return | ||
} | ||
|
||
// leaked credentials doens't offer a single get operation so | ||
// loop until we find the matching ID. | ||
for _, rule := range rules { | ||
if rule.ID == state.ID.ValueString() { | ||
foundRule = rule | ||
break | ||
} | ||
} | ||
|
||
state.Password = types.StringValue(foundRule.Password) | ||
state.Username = types.StringValue(foundRule.Username) | ||
state.ID = types.StringValue(foundRule.ID) | ||
state.ZoneID = types.StringValue(zoneID) | ||
|
||
diags = resp.State.Set(ctx, &state) | ||
resp.Diagnostics.Append(diags...) | ||
} | ||
|
||
func (r *LeakedCredentialCheckRuleResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { | ||
var data LeakedCredentialCheckRulesModel | ||
diags := req.Plan.Get(ctx, &data) | ||
resp.Diagnostics.Append(diags...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
zoneID := cloudflare.ZoneIdentifier(data.ZoneID.ValueString()) | ||
_, err := r.client.V1.LeakedCredentialCheckUpdateDetection(ctx, zoneID, cloudflare.LeakedCredentialCheckUpdateDetectionParams{ | ||
LeakedCredentialCheckDetectionEntry: cloudflare.LeakedCredentialCheckDetectionEntry{ | ||
ID: data.ID.ValueString(), | ||
Username: data.Username.ValueString(), | ||
Password: data.Password.ValueString(), | ||
}, | ||
}) | ||
if err != nil { | ||
resp.Diagnostics.AddError("Error fetching Leaked Credential Check user-defined detection patterns", err.Error()) | ||
return | ||
} | ||
|
||
diags = resp.State.Set(ctx, &data) | ||
resp.Diagnostics.Append(diags...) | ||
} | ||
|
||
func (r *LeakedCredentialCheckRuleResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { | ||
var state LeakedCredentialCheckRulesModel | ||
diags := req.State.Get(ctx, &state) | ||
resp.Diagnostics.Append(diags...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
zoneID := cloudflare.ZoneIdentifier(state.ZoneID.ValueString()) | ||
deleteParam := cloudflare.LeakedCredentialCheckDeleteDetectionParams{DetectionID: state.ID.ValueString()} | ||
_, err := r.client.V1.LeakedCredentialCheckDeleteDetection(ctx, zoneID, deleteParam) | ||
if err != nil { | ||
resp.Diagnostics.AddError("Error deleting a user-defined detection patter for Leaked Credential Check", err.Error()) | ||
return | ||
} | ||
} | ||
|
||
func (r *LeakedCredentialCheckRuleResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { | ||
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("id"), req.ID)...) | ||
return | ||
} |
102 changes: 102 additions & 0 deletions
102
internal/framework/service/leaked_credential_check_rule/resource_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
package leaked_credential_check_rule_test | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"fmt" | ||
"os" | ||
"testing" | ||
|
||
cfv1 "github.com/cloudflare/cloudflare-go" | ||
"github.com/cloudflare/terraform-provider-cloudflare/internal/acctest" | ||
"github.com/cloudflare/terraform-provider-cloudflare/internal/utils" | ||
|
||
"github.com/hashicorp/terraform-plugin-log/tflog" | ||
"github.com/hashicorp/terraform-plugin-testing/helper/resource" | ||
) | ||
|
||
func init() { | ||
resource.AddTestSweepers("cloudflare_leaked_credential_check_rule", &resource.Sweeper{ | ||
Name: "cloudflare_leaked_credential_check_rule", | ||
F: testSweepCloudflareLCCRules, | ||
}) | ||
} | ||
|
||
func testSweepCloudflareLCCRules(r string) error { | ||
ctx := context.Background() | ||
client, clientErr := acctest.SharedV1Client() | ||
if clientErr != nil { | ||
tflog.Error(ctx, fmt.Sprintf("Failed to create Cloudflare client: %s", clientErr)) | ||
} | ||
|
||
zoneID := os.Getenv("CLOUDFLARE_ZONE_ID") | ||
if zoneID == "" { | ||
return errors.New("CLOUDFLARE_ZONE_ID must be set") | ||
} | ||
// fetch existing rules from API | ||
rules, err := client.LeakedCredentialCheckListDetections(ctx, cfv1.ZoneIdentifier(zoneID), cfv1.LeakedCredentialCheckListDetectionsParams{}) | ||
if err != nil { | ||
tflog.Error(ctx, fmt.Sprintf("Error fetching Leaked Credential Check user-defined detection patterns: %s", err)) | ||
return err | ||
} | ||
for _, rule := range rules { | ||
deleteParam := cfv1.LeakedCredentialCheckDeleteDetectionParams{DetectionID: rule.ID} | ||
_, err := client.LeakedCredentialCheckDeleteDetection(ctx, cfv1.ZoneIdentifier(zoneID), deleteParam) | ||
if err != nil { | ||
tflog.Error(ctx, fmt.Sprintf("Error deleting a user-defined detection patter for Leaked Credential Check: %s", err)) | ||
} | ||
|
||
} | ||
return nil | ||
} | ||
|
||
func TestAccCloudflareLeakedCredentialCheckRule_Basic(t *testing.T) { | ||
rnd := utils.GenerateRandomResourceName() | ||
name := fmt.Sprintf("cloudflare_leaked_credential_check_rule.%s", rnd) | ||
zoneID := os.Getenv("CLOUDFLARE_ZONE_ID") | ||
|
||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { | ||
acctest.TestAccPreCheck(t) | ||
}, | ||
ProtoV6ProviderFactories: acctest.TestAccProtoV6ProviderFactories, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccConfigAddHeader(rnd, zoneID, testAccLCCTwoSimpleRules(rnd)), | ||
Check: resource.ComposeTestCheckFunc( | ||
resource.TestCheckResourceAttr(name+"_first", "zone_id", zoneID), | ||
resource.TestCheckResourceAttr(name+"_first", "username", "lookup_json_string(http.request.body.raw, \"user\")"), | ||
resource.TestCheckResourceAttr(name+"_first", "password", "lookup_json_string(http.request.body.raw, \"pass\")"), | ||
|
||
resource.TestCheckResourceAttr(name+"_second", "zone_id", zoneID), | ||
resource.TestCheckResourceAttr(name+"_second", "username", "lookup_json_string(http.request.body.raw, \"id\")"), | ||
resource.TestCheckResourceAttr(name+"_second", "password", "lookup_json_string(http.request.body.raw, \"secret\")"), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func testAccConfigAddHeader(name, zoneID, config string) string { | ||
header := fmt.Sprintf(` | ||
resource "cloudflare_leaked_credential_check" "%[1]s" { | ||
zone_id = "%[2]s" | ||
enabled = true | ||
}`, name, zoneID) | ||
return header + "\n" + config | ||
} | ||
|
||
func testAccLCCTwoSimpleRules(name string) string { | ||
return fmt.Sprintf(` | ||
resource "cloudflare_leaked_credential_check_rule" "%[1]s_first" { | ||
zone_id = cloudflare_leaked_credential_check.%[1]s.zone_id | ||
username = "lookup_json_string(http.request.body.raw, \"user\")" | ||
password = "lookup_json_string(http.request.body.raw, \"pass\")" | ||
} | ||
resource "cloudflare_leaked_credential_check_rule" "%[1]s_second" { | ||
zone_id = cloudflare_leaked_credential_check.%[1]s.zone_id | ||
username = "lookup_json_string(http.request.body.raw, \"id\")" | ||
password = "lookup_json_string(http.request.body.raw, \"secret\")" | ||
}`, name) | ||
} |
33 changes: 33 additions & 0 deletions
33
internal/framework/service/leaked_credential_check_rule/schema.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package leaked_credential_check_rule | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/cloudflare/terraform-provider-cloudflare/internal/consts" | ||
"github.com/hashicorp/terraform-plugin-framework/resource" | ||
"github.com/hashicorp/terraform-plugin-framework/resource/schema" | ||
) | ||
|
||
func (r *LeakedCredentialCheckRuleResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { | ||
resp.Schema = schema.Schema{ | ||
Description: "Provides a Cloudflare Leaked Credential Check Rules resource for managing user-defined Leaked Credential detection patterns within a specific zone.", | ||
Attributes: map[string]schema.Attribute{ | ||
consts.IDSchemaKey: schema.StringAttribute{ | ||
Description: consts.IDSchemaDescription, | ||
Computed: true, | ||
}, | ||
consts.ZoneIDSchemaKey: schema.StringAttribute{ | ||
Description: consts.ZoneIDSchemaDescription, | ||
Required: true, | ||
}, | ||
"username": schema.StringAttribute{ | ||
Description: "The ruleset expression to use in matching the username in a request.", | ||
Required: true, | ||
}, | ||
"password": schema.StringAttribute{ | ||
Description: "The ruleset expression to use in matching the password in a request", | ||
Required: true, | ||
}, | ||
}, | ||
} | ||
} |
Oops, something went wrong.