diff --git a/client/project_protection_bypass_for_automation_update.go b/client/project_protection_bypass_for_automation_update.go index d721539f..667c8b56 100644 --- a/client/project_protection_bypass_for_automation_update.go +++ b/client/project_protection_bypass_for_automation_update.go @@ -19,9 +19,22 @@ type revokeBypassProtectionRequest struct { Secret string `json:"secret"` } +type generateBypassProtectionRequest struct { + Secret string `json:"secret"` +} + func getUpdateBypassProtectionRequestBody(newValue bool, secret string) string { if newValue { - return "{}" + if secret == "" { + return "{}" + } + return string(mustMarshal(struct { + Revoke generateBypassProtectionRequest `json:"generate"` + }{ + Revoke: generateBypassProtectionRequest{ + Secret: secret, + }, + })) } return string(mustMarshal(struct { @@ -57,7 +70,7 @@ func (c *Client) UpdateProtectionBypassForAutomation(ctx context.Context, reques }, &response) if err != nil { - return s, fmt.Errorf("unable to add protection bypass for automation: %w", err) + return s, fmt.Errorf("unable to update protection bypass for automation: %w", err) } if !request.NewValue { diff --git a/docs/data-sources/project.md b/docs/data-sources/project.md index 7fd4096d..78c3a4a2 100644 --- a/docs/data-sources/project.md +++ b/docs/data-sources/project.md @@ -59,7 +59,8 @@ data "vercel_project" "example" { - `password_protection` (Attributes) Ensures visitors of your Preview Deployments must enter a password in order to gain access. (see [below for nested schema](#nestedatt--password_protection)) - `preview_comments` (Boolean) Whether comments are enabled on your Preview Deployments. - `prioritise_production_builds` (Boolean) If enabled, builds for the Production environment will be prioritized over Preview environments. -- `protection_bypass_for_automation` (Boolean) Allows automation services to bypass Vercel Authentication and Password Protection for both Preview and Production Deployments on this project when using an HTTP header named `x-vercel-protection-bypass`. +- `protection_bypass_for_automation` (Boolean) Allows automation services to bypass Deployment Protection on this project when using an HTTP header named `x-vercel-protection-bypass` with the value from `protection_bypass_for_automation_secret`. +- `protection_bypass_for_automation_secret` (String, Sensitive) If `protection_bypass_for_automation` is enabled, optionally set this value to specify a 32 character secret, otherwise a secret will be generated. - `public_source` (Boolean) Specifies whether the source code and logs of the deployments for this project should be public or not. - `resource_config` (Attributes) Resource Configuration for the project. (see [below for nested schema](#nestedatt--resource_config)) - `root_directory` (String) The name of a directory or relative path to the source code of your project. When null is used it will default to the project root. diff --git a/docs/resources/project.md b/docs/resources/project.md index 67966aa8..242c288a 100644 --- a/docs/resources/project.md +++ b/docs/resources/project.md @@ -76,7 +76,8 @@ resource "vercel_project" "example" { - `password_protection` (Attributes) Ensures visitors of your Preview Deployments must enter a password in order to gain access. (see [below for nested schema](#nestedatt--password_protection)) - `preview_comments` (Boolean) Whether to enable comments on your Preview Deployments. If omitted, comments are controlled at the team level (default behaviour). - `prioritise_production_builds` (Boolean) If enabled, builds for the Production environment will be prioritized over Preview environments. -- `protection_bypass_for_automation` (Boolean) Allow automation services to bypass Vercel Authentication and Password Protection for both Preview and Production Deployments on this project when using an HTTP header named `x-vercel-protection-bypass` with a value of the `password_protection_for_automation_secret` field. +- `protection_bypass_for_automation` (Boolean) Allow automation services to bypass Deployment Protection on this project when using an HTTP header named `x-vercel-protection-bypass` with a value of the `protection_bypass_for_automation_secret` field. +- `protection_bypass_for_automation_secret` (String, Sensitive) If `protection_bypass_for_automation` is enabled, optionally set this value to specify a 32 character secret, otherwise a secret will be generated. - `public_source` (Boolean) By default, visitors to the `/_logs` and `/_src` paths of your Production and Preview Deployments must log in with Vercel (requires being a member of your team) to see the Source, Logs and Deployment Status of your project. Setting `public_source` to `true` disables this behaviour, meaning the Source, Logs and Deployment Status can be publicly viewed. - `resource_config` (Attributes) Resource Configuration for the project. (see [below for nested schema](#nestedatt--resource_config)) - `root_directory` (String) The name of a directory or relative path to the source code of your project. If omitted, it will default to the project root. @@ -89,7 +90,6 @@ resource "vercel_project" "example" { ### Read-Only - `id` (String) The ID of this resource. -- `protection_bypass_for_automation_secret` (String) If `protection_bypass_for_automation` is enabled, use this value in the `x-vercel-protection-bypass` header to bypass Vercel Authentication and Password Protection for both Preview and Production Deployments. ### Nested Schema for `environment` diff --git a/vercel/data_source_project.go b/vercel/data_source_project.go index 855ec8bd..c5ece7ee 100644 --- a/vercel/data_source_project.go +++ b/vercel/data_source_project.go @@ -279,7 +279,19 @@ For more detailed information, please see the [Vercel documentation](https://ver }, "protection_bypass_for_automation": schema.BoolAttribute{ Computed: true, - Description: "Allows automation services to bypass Vercel Authentication and Password Protection for both Preview and Production Deployments on this project when using an HTTP header named `x-vercel-protection-bypass`.", + Description: "Allows automation services to bypass Deployment Protection on this project when using an HTTP header named `x-vercel-protection-bypass` with the value from `protection_bypass_for_automation_secret`.", + }, + "protection_bypass_for_automation_secret": schema.StringAttribute{ + Sensitive: true, + Computed: true, + Description: "If `protection_bypass_for_automation` is enabled, optionally set this value to specify a 32 character secret, otherwise a secret will be generated.", + Validators: []validator.String{ + stringvalidator.RegexMatches( + regexp.MustCompile(`^[a-zA-Z0-9]{32}$`), + "Specify `generate` to have the value generated automatically, or specify a 32 character secret.", + ), + validateAutomationBypassSecret(), + }, }, "automatically_expose_system_environment_variables": schema.BoolAttribute{ Computed: true, @@ -356,38 +368,39 @@ For more detailed information, please see the [Vercel documentation](https://ver // Project reflects the state terraform stores internally for a project. type ProjectDataSource struct { - BuildCommand types.String `tfsdk:"build_command"` - DevCommand types.String `tfsdk:"dev_command"` - Environment types.Set `tfsdk:"environment"` - Framework types.String `tfsdk:"framework"` - GitRepository *GitRepository `tfsdk:"git_repository"` - ID types.String `tfsdk:"id"` - IgnoreCommand types.String `tfsdk:"ignore_command"` - InstallCommand types.String `tfsdk:"install_command"` - Name types.String `tfsdk:"name"` - OutputDirectory types.String `tfsdk:"output_directory"` - PublicSource types.Bool `tfsdk:"public_source"` - RootDirectory types.String `tfsdk:"root_directory"` - ServerlessFunctionRegion types.String `tfsdk:"serverless_function_region"` - TeamID types.String `tfsdk:"team_id"` - VercelAuthentication *VercelAuthentication `tfsdk:"vercel_authentication"` - PasswordProtection *PasswordProtection `tfsdk:"password_protection"` - TrustedIps *TrustedIps `tfsdk:"trusted_ips"` - OIDCTokenConfig *OIDCTokenConfig `tfsdk:"oidc_token_config"` - OptionsAllowlist *OptionsAllowlist `tfsdk:"options_allowlist"` - ProtectionBypassForAutomation types.Bool `tfsdk:"protection_bypass_for_automation"` - AutoExposeSystemEnvVars types.Bool `tfsdk:"automatically_expose_system_environment_variables"` - GitComments types.Object `tfsdk:"git_comments"` - PreviewComments types.Bool `tfsdk:"preview_comments"` - AutoAssignCustomDomains types.Bool `tfsdk:"auto_assign_custom_domains"` - GitLFS types.Bool `tfsdk:"git_lfs"` - FunctionFailover types.Bool `tfsdk:"function_failover"` - CustomerSuccessCodeVisibility types.Bool `tfsdk:"customer_success_code_visibility"` - GitForkProtection types.Bool `tfsdk:"git_fork_protection"` - PrioritiseProductionBuilds types.Bool `tfsdk:"prioritise_production_builds"` - DirectoryListing types.Bool `tfsdk:"directory_listing"` - SkewProtection types.String `tfsdk:"skew_protection"` - ResourceConfig *ResourceConfig `tfsdk:"resource_config"` + BuildCommand types.String `tfsdk:"build_command"` + DevCommand types.String `tfsdk:"dev_command"` + Environment types.Set `tfsdk:"environment"` + Framework types.String `tfsdk:"framework"` + GitRepository *GitRepository `tfsdk:"git_repository"` + ID types.String `tfsdk:"id"` + IgnoreCommand types.String `tfsdk:"ignore_command"` + InstallCommand types.String `tfsdk:"install_command"` + Name types.String `tfsdk:"name"` + OutputDirectory types.String `tfsdk:"output_directory"` + PublicSource types.Bool `tfsdk:"public_source"` + RootDirectory types.String `tfsdk:"root_directory"` + ServerlessFunctionRegion types.String `tfsdk:"serverless_function_region"` + TeamID types.String `tfsdk:"team_id"` + VercelAuthentication *VercelAuthentication `tfsdk:"vercel_authentication"` + PasswordProtection *PasswordProtection `tfsdk:"password_protection"` + TrustedIps *TrustedIps `tfsdk:"trusted_ips"` + OIDCTokenConfig *OIDCTokenConfig `tfsdk:"oidc_token_config"` + OptionsAllowlist *OptionsAllowlist `tfsdk:"options_allowlist"` + ProtectionBypassForAutomation types.Bool `tfsdk:"protection_bypass_for_automation"` + ProtectionBypassForAutomationSecret types.String `tfsdk:"protection_bypass_for_automation_secret"` + AutoExposeSystemEnvVars types.Bool `tfsdk:"automatically_expose_system_environment_variables"` + GitComments types.Object `tfsdk:"git_comments"` + PreviewComments types.Bool `tfsdk:"preview_comments"` + AutoAssignCustomDomains types.Bool `tfsdk:"auto_assign_custom_domains"` + GitLFS types.Bool `tfsdk:"git_lfs"` + FunctionFailover types.Bool `tfsdk:"function_failover"` + CustomerSuccessCodeVisibility types.Bool `tfsdk:"customer_success_code_visibility"` + GitForkProtection types.Bool `tfsdk:"git_fork_protection"` + PrioritiseProductionBuilds types.Bool `tfsdk:"prioritise_production_builds"` + DirectoryListing types.Bool `tfsdk:"directory_listing"` + SkewProtection types.String `tfsdk:"skew_protection"` + ResourceConfig *ResourceConfig `tfsdk:"resource_config"` } func convertResponseToProjectDataSource(ctx context.Context, response client.ProjectResponse, plan Project, environmentVariables []client.EnvironmentVariable) (ProjectDataSource, error) { @@ -421,39 +434,41 @@ func convertResponseToProjectDataSource(ctx context.Context, response client.Pro DeploymentType: project.PasswordProtection.DeploymentType, } } + return ProjectDataSource{ - BuildCommand: project.BuildCommand, - DevCommand: project.DevCommand, - Environment: project.Environment, - Framework: project.Framework, - GitRepository: project.GitRepository, - ID: project.ID, - IgnoreCommand: project.IgnoreCommand, - InstallCommand: project.InstallCommand, - Name: project.Name, - OutputDirectory: project.OutputDirectory, - PublicSource: project.PublicSource, - RootDirectory: project.RootDirectory, - ServerlessFunctionRegion: project.ServerlessFunctionRegion, - TeamID: project.TeamID, - VercelAuthentication: project.VercelAuthentication, - PasswordProtection: pp, - TrustedIps: project.TrustedIps, - OIDCTokenConfig: project.OIDCTokenConfig, - OptionsAllowlist: project.OptionsAllowlist, - AutoExposeSystemEnvVars: types.BoolPointerValue(response.AutoExposeSystemEnvVars), - ProtectionBypassForAutomation: project.ProtectionBypassForAutomation, - GitComments: project.GitComments, - PreviewComments: project.PreviewComments, - AutoAssignCustomDomains: project.AutoAssignCustomDomains, - GitLFS: project.GitLFS, - FunctionFailover: project.FunctionFailover, - CustomerSuccessCodeVisibility: project.CustomerSuccessCodeVisibility, - GitForkProtection: project.GitForkProtection, - PrioritiseProductionBuilds: project.PrioritiseProductionBuilds, - DirectoryListing: project.DirectoryListing, - SkewProtection: project.SkewProtection, - ResourceConfig: project.ResourceConfig, + BuildCommand: project.BuildCommand, + DevCommand: project.DevCommand, + Environment: project.Environment, + Framework: project.Framework, + GitRepository: project.GitRepository, + ID: project.ID, + IgnoreCommand: project.IgnoreCommand, + InstallCommand: project.InstallCommand, + Name: project.Name, + OutputDirectory: project.OutputDirectory, + PublicSource: project.PublicSource, + RootDirectory: project.RootDirectory, + ServerlessFunctionRegion: project.ServerlessFunctionRegion, + TeamID: project.TeamID, + VercelAuthentication: project.VercelAuthentication, + PasswordProtection: pp, + TrustedIps: project.TrustedIps, + OIDCTokenConfig: project.OIDCTokenConfig, + OptionsAllowlist: project.OptionsAllowlist, + AutoExposeSystemEnvVars: types.BoolPointerValue(response.AutoExposeSystemEnvVars), + ProtectionBypassForAutomation: project.ProtectionBypassForAutomation, + ProtectionBypassForAutomationSecret: project.ProtectionBypassForAutomationSecret, + GitComments: project.GitComments, + PreviewComments: project.PreviewComments, + AutoAssignCustomDomains: project.AutoAssignCustomDomains, + GitLFS: project.GitLFS, + FunctionFailover: project.FunctionFailover, + CustomerSuccessCodeVisibility: project.CustomerSuccessCodeVisibility, + GitForkProtection: project.GitForkProtection, + PrioritiseProductionBuilds: project.PrioritiseProductionBuilds, + DirectoryListing: project.DirectoryListing, + SkewProtection: project.SkewProtection, + ResourceConfig: project.ResourceConfig, }, nil } diff --git a/vercel/resource_project.go b/vercel/resource_project.go index 4dda97cc..60cf2523 100644 --- a/vercel/resource_project.go +++ b/vercel/resource_project.go @@ -387,11 +387,20 @@ At this time you cannot use a Vercel Project resource with in-line ` + "`environ }, "protection_bypass_for_automation": schema.BoolAttribute{ Optional: true, - Description: "Allow automation services to bypass Vercel Authentication and Password Protection for both Preview and Production Deployments on this project when using an HTTP header named `x-vercel-protection-bypass` with a value of the `password_protection_for_automation_secret` field.", + Description: "Allow automation services to bypass Deployment Protection on this project when using an HTTP header named `x-vercel-protection-bypass` with a value of the `protection_bypass_for_automation_secret` field.", }, "protection_bypass_for_automation_secret": schema.StringAttribute{ Computed: true, - Description: "If `protection_bypass_for_automation` is enabled, use this value in the `x-vercel-protection-bypass` header to bypass Vercel Authentication and Password Protection for both Preview and Production Deployments.", + Optional: true, + Sensitive: true, + Description: "If `protection_bypass_for_automation` is enabled, optionally set this value to specify a 32 character secret, otherwise a secret will be generated.", + Validators: []validator.String{ + stringvalidator.RegexMatches( + regexp.MustCompile(`^[a-zA-Z0-9]{32}$`), + "Specify `generate` to have the value generated automatically, or specify a 32 character secret.", + ), + validateAutomationBypassSecret(), + }, }, "automatically_expose_system_environment_variables": schema.BoolAttribute{ Optional: true, @@ -1244,6 +1253,9 @@ func convertResponseToProject(ctx context.Context, response client.ProjectRespon if !plan.ProtectionBypassForAutomation.IsNull() && !plan.ProtectionBypassForAutomation.ValueBool() { protectionBypass = types.BoolValue(false) } + if plan.ProtectionBypassForAutomationSecret.ValueString() != "" { + protectionBypassSecret = types.StringValue(plan.ProtectionBypassForAutomationSecret.ValueString()) + } environmentEntry := types.SetValueMust(envVariableElemType, env) if plan.Environment.IsNull() { @@ -1499,6 +1511,7 @@ func (r *projectResource) Create(ctx context.Context, req resource.CreateRequest ProjectID: result.ID.ValueString(), TeamID: result.TeamID.ValueString(), NewValue: true, + Secret: plan.ProtectionBypassForAutomationSecret.ValueString(), }) if err != nil { resp.Diagnostics.AddError( @@ -1778,11 +1791,15 @@ func (r *projectResource) Update(ctx context.Context, req resource.UpdateRequest } if state.ProtectionBypassForAutomation != plan.ProtectionBypassForAutomation { + secret := state.ProtectionBypassForAutomationSecret.ValueString() + if plan.ProtectionBypassForAutomationSecret.ValueString() != "" { + secret = plan.ProtectionBypassForAutomationSecret.ValueString() + } _, err := r.client.UpdateProtectionBypassForAutomation(ctx, client.UpdateProtectionBypassForAutomationRequest{ ProjectID: plan.ID.ValueString(), TeamID: plan.TeamID.ValueString(), NewValue: plan.ProtectionBypassForAutomation.ValueBool(), - Secret: state.ProtectionBypassForAutomationSecret.ValueString(), + Secret: secret, }) if err != nil { resp.Diagnostics.AddError( diff --git a/vercel/resource_project_test.go b/vercel/resource_project_test.go index 2cbad9ce..b135bd3a 100644 --- a/vercel/resource_project_test.go +++ b/vercel/resource_project_test.go @@ -328,6 +328,48 @@ func TestAcc_ProjectWithVercelAuthAndPasswordProtectionAndTrustedIps(t *testing. }) } +func TestAcc_ProjectWithAutomationBypass(t *testing.T) { + projectSuffix := acctest.RandString(16) + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + CheckDestroy: testAccProjectDestroy("vercel_project.disabled_to_enabled_generated_secret", testTeam()), + Steps: []resource.TestStep{ + { + Config: testAccProjectConfigAutomationBypass(projectSuffix, teamIDConfig()), + Check: resource.ComposeAggregateTestCheckFunc( + testAccProjectExists("vercel_project.disabled_to_enabled_generated_secret", testTeam()), + resource.TestCheckNoResourceAttr("vercel_project.disabled_to_enabled_generated_secret", "protection_bypass_for_automation"), + testAccProjectExists("vercel_project.disabled_to_enabled_custom_secret", testTeam()), + resource.TestCheckNoResourceAttr("vercel_project.disabled_to_enabled_custom_secret", "protection_bypass_for_automation"), + testAccProjectExists("vercel_project.enabled_generated_secret_to_enabled_custom_secret", testTeam()), + resource.TestCheckResourceAttr("vercel_project.enabled_generated_secret_to_enabled_custom_secret", "protection_bypass_for_automation", "true"), + resource.TestCheckResourceAttrSet("vercel_project.enabled_generated_secret_to_enabled_custom_secret", "protection_bypass_for_automation_secret"), + testAccProjectExists("vercel_project.enabled_generated_secret_to_disabled", testTeam()), + resource.TestCheckResourceAttr("vercel_project.enabled_generated_secret_to_disabled", "protection_bypass_for_automation", "true"), + resource.TestCheckResourceAttrSet("vercel_project.enabled_generated_secret_to_disabled", "protection_bypass_for_automation_secret"), + testAccProjectExists("vercel_project.enabled_custom_secret_to_disabled", testTeam()), + resource.TestCheckResourceAttr("vercel_project.enabled_custom_secret_to_disabled", "protection_bypass_for_automation", "true"), + resource.TestCheckResourceAttr("vercel_project.enabled_custom_secret_to_disabled", "protection_bypass_for_automation_secret", "12345678912345678912345678912345"), + ), + }, + { + Config: testAccProjectConfigAutomationBypassUpdate(projectSuffix, teamIDConfig()), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("vercel_project.disabled_to_enabled_generated_secret", "protection_bypass_for_automation", "true"), + resource.TestCheckResourceAttrSet("vercel_project.disabled_to_enabled_generated_secret", "protection_bypass_for_automation_secret"), + resource.TestCheckResourceAttr("vercel_project.disabled_to_enabled_custom_secret", "protection_bypass_for_automation", "true"), + resource.TestCheckResourceAttr("vercel_project.disabled_to_enabled_custom_secret", "protection_bypass_for_automation_secret", "12345678912345678912345678912345"), + resource.TestCheckResourceAttr("vercel_project.enabled_generated_secret_to_enabled_custom_secret", "protection_bypass_for_automation", "true"), + resource.TestCheckResourceAttr("vercel_project.enabled_generated_secret_to_enabled_custom_secret", "protection_bypass_for_automation_secret", "12345678912345678912345678912345"), + resource.TestCheckResourceAttr("vercel_project.enabled_generated_secret_to_disabled", "protection_bypass_for_automation", "false"), + resource.TestCheckResourceAttr("vercel_project.enabled_custom_secret_to_disabled", "protection_bypass_for_automation", "false"), + ), + }, + }, + }) +} + func getProjectImportID(n string) resource.ImportStateIdFunc { return func(s *terraform.State) (string, error) { rs, ok := s.RootModule().Resources[n] @@ -626,6 +668,75 @@ resource "vercel_project" "enabled_to_update" { `, projectSuffix, teamID) } +func testAccProjectConfigAutomationBypass(projectSuffix, teamID string) string { + return fmt.Sprintf(` +resource "vercel_project" "disabled_to_enabled_generated_secret" { + name = "test-acc-automation-bypass-one-%[1]s" + %[2]s +} + +resource "vercel_project" "disabled_to_enabled_custom_secret" { + name = "test-acc-automation-bypass-two-%[1]s" + %[2]s +} + +resource "vercel_project" "enabled_generated_secret_to_enabled_custom_secret" { + name = "test-acc-automation-bypass-three-%[1]s" + %[2]s + protection_bypass_for_automation = true +} + +resource "vercel_project" "enabled_generated_secret_to_disabled" { + name = "test-acc-automation-bypass-four-%[1]s" + %[2]s + protection_bypass_for_automation = true +} + +resource "vercel_project" "enabled_custom_secret_to_disabled" { + name = "test-acc-automation-bypass-five-%[1]s" + %[2]s + protection_bypass_for_automation = true + protection_bypass_for_automation_secret = "12345678912345678912345678912345" +} + `, projectSuffix, teamID) +} + +func testAccProjectConfigAutomationBypassUpdate(projectSuffix, teamID string) string { + return fmt.Sprintf(` +resource "vercel_project" "disabled_to_enabled_generated_secret" { + name = "test-acc-automation-bypass-one-%[1]s" + %[2]s + protection_bypass_for_automation = true +} + +resource "vercel_project" "disabled_to_enabled_custom_secret" { + name = "test-acc-automation-bypass-two-%[1]s" + %[2]s + protection_bypass_for_automation = true + protection_bypass_for_automation_secret = "12345678912345678912345678912345" +} + +resource "vercel_project" "enabled_generated_secret_to_enabled_custom_secret" { + name = "test-acc-automation-bypass-three-%[1]s" + %[2]s + protection_bypass_for_automation = true + protection_bypass_for_automation_secret = "12345678912345678912345678912345" +} + +resource "vercel_project" "enabled_generated_secret_to_disabled" { + name = "test-acc-automation-bypass-four-%[1]s" + %[2]s + protection_bypass_for_automation = false +} + +resource "vercel_project" "enabled_custom_secret_to_disabled" { + name = "test-acc-automation-bypass-five-%[1]s" + %[2]s + protection_bypass_for_automation = false +} + `, projectSuffix, teamID) +} + func testAccProjectConfigWithGitRepo(projectSuffix, teamID string) string { return fmt.Sprintf(` resource "vercel_project" "test_git" { diff --git a/vercel/validator_automation_bypass_secret.go b/vercel/validator_automation_bypass_secret.go new file mode 100644 index 00000000..9d75f2ca --- /dev/null +++ b/vercel/validator_automation_bypass_secret.go @@ -0,0 +1,45 @@ +package vercel + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +var _ validator.String = validateAutomationBypassSecretConditional{} + +func validateAutomationBypassSecret() validateAutomationBypassSecretConditional { + return validateAutomationBypassSecretConditional{} +} + +type validateAutomationBypassSecretConditional struct{} + +func (v validateAutomationBypassSecretConditional) Description(ctx context.Context) string { + return "protection_bypass_for_automation_secret is only allowed when protection_bypass_for_automation is true" +} + +func (v validateAutomationBypassSecretConditional) MarkdownDescription(ctx context.Context) string { + return "protection_bypass_for_automation_secret is only allowed when protection_bypass_for_automation is true" +} + +func (v validateAutomationBypassSecretConditional) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) { + if req.ConfigValue.IsUnknown() || req.ConfigValue.IsNull() { + return + } + + enabled := types.Bool{} + if diags := req.Config.GetAttribute(ctx, path.Root("protection_bypass_for_automation"), &enabled); diags.HasError() { + resp.Diagnostics.Append(diags...) + return + } + + if !enabled.ValueBool() { + resp.Diagnostics.AddAttributeError( + req.Path, + "Invalid Configuration", + "protection_bypass_for_automation_secret is not allowed unless protection_bypass_for_automation is true.", + ) + } +}