Skip to content

Commit 46377a7

Browse files
authored
Add support for customisable automation bypass secret (#239)
Add support for customisable automation bypass secret
1 parent e2bd728 commit 46377a7

File tree

7 files changed

+275
-73
lines changed

7 files changed

+275
-73
lines changed

client/project_protection_bypass_for_automation_update.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,22 @@ type revokeBypassProtectionRequest struct {
1919
Secret string `json:"secret"`
2020
}
2121

22+
type generateBypassProtectionRequest struct {
23+
Secret string `json:"secret"`
24+
}
25+
2226
func getUpdateBypassProtectionRequestBody(newValue bool, secret string) string {
2327
if newValue {
24-
return "{}"
28+
if secret == "" {
29+
return "{}"
30+
}
31+
return string(mustMarshal(struct {
32+
Revoke generateBypassProtectionRequest `json:"generate"`
33+
}{
34+
Revoke: generateBypassProtectionRequest{
35+
Secret: secret,
36+
},
37+
}))
2538
}
2639

2740
return string(mustMarshal(struct {
@@ -57,7 +70,7 @@ func (c *Client) UpdateProtectionBypassForAutomation(ctx context.Context, reques
5770
}, &response)
5871

5972
if err != nil {
60-
return s, fmt.Errorf("unable to add protection bypass for automation: %w", err)
73+
return s, fmt.Errorf("unable to update protection bypass for automation: %w", err)
6174
}
6275

6376
if !request.NewValue {

docs/data-sources/project.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ data "vercel_project" "example" {
5959
- `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))
6060
- `preview_comments` (Boolean) Whether comments are enabled on your Preview Deployments.
6161
- `prioritise_production_builds` (Boolean) If enabled, builds for the Production environment will be prioritized over Preview environments.
62-
- `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`.
62+
- `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`.
63+
- `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.
6364
- `public_source` (Boolean) Specifies whether the source code and logs of the deployments for this project should be public or not.
6465
- `resource_config` (Attributes) Resource Configuration for the project. (see [below for nested schema](#nestedatt--resource_config))
6566
- `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.

docs/resources/project.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ resource "vercel_project" "example" {
7676
- `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))
7777
- `preview_comments` (Boolean) Whether to enable comments on your Preview Deployments. If omitted, comments are controlled at the team level (default behaviour).
7878
- `prioritise_production_builds` (Boolean) If enabled, builds for the Production environment will be prioritized over Preview environments.
79-
- `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.
79+
- `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.
80+
- `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.
8081
- `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.
8182
- `resource_config` (Attributes) Resource Configuration for the project. (see [below for nested schema](#nestedatt--resource_config))
8283
- `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" {
8990
### Read-Only
9091

9192
- `id` (String) The ID of this resource.
92-
- `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.
9393

9494
<a id="nestedatt--environment"></a>
9595
### Nested Schema for `environment`

vercel/data_source_project.go

Lines changed: 80 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,19 @@ For more detailed information, please see the [Vercel documentation](https://ver
279279
},
280280
"protection_bypass_for_automation": schema.BoolAttribute{
281281
Computed: true,
282-
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`.",
282+
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`.",
283+
},
284+
"protection_bypass_for_automation_secret": schema.StringAttribute{
285+
Sensitive: true,
286+
Computed: true,
287+
Description: "If `protection_bypass_for_automation` is enabled, optionally set this value to specify a 32 character secret, otherwise a secret will be generated.",
288+
Validators: []validator.String{
289+
stringvalidator.RegexMatches(
290+
regexp.MustCompile(`^[a-zA-Z0-9]{32}$`),
291+
"Specify `generate` to have the value generated automatically, or specify a 32 character secret.",
292+
),
293+
validateAutomationBypassSecret(),
294+
},
283295
},
284296
"automatically_expose_system_environment_variables": schema.BoolAttribute{
285297
Computed: true,
@@ -356,38 +368,39 @@ For more detailed information, please see the [Vercel documentation](https://ver
356368

357369
// Project reflects the state terraform stores internally for a project.
358370
type ProjectDataSource struct {
359-
BuildCommand types.String `tfsdk:"build_command"`
360-
DevCommand types.String `tfsdk:"dev_command"`
361-
Environment types.Set `tfsdk:"environment"`
362-
Framework types.String `tfsdk:"framework"`
363-
GitRepository *GitRepository `tfsdk:"git_repository"`
364-
ID types.String `tfsdk:"id"`
365-
IgnoreCommand types.String `tfsdk:"ignore_command"`
366-
InstallCommand types.String `tfsdk:"install_command"`
367-
Name types.String `tfsdk:"name"`
368-
OutputDirectory types.String `tfsdk:"output_directory"`
369-
PublicSource types.Bool `tfsdk:"public_source"`
370-
RootDirectory types.String `tfsdk:"root_directory"`
371-
ServerlessFunctionRegion types.String `tfsdk:"serverless_function_region"`
372-
TeamID types.String `tfsdk:"team_id"`
373-
VercelAuthentication *VercelAuthentication `tfsdk:"vercel_authentication"`
374-
PasswordProtection *PasswordProtection `tfsdk:"password_protection"`
375-
TrustedIps *TrustedIps `tfsdk:"trusted_ips"`
376-
OIDCTokenConfig *OIDCTokenConfig `tfsdk:"oidc_token_config"`
377-
OptionsAllowlist *OptionsAllowlist `tfsdk:"options_allowlist"`
378-
ProtectionBypassForAutomation types.Bool `tfsdk:"protection_bypass_for_automation"`
379-
AutoExposeSystemEnvVars types.Bool `tfsdk:"automatically_expose_system_environment_variables"`
380-
GitComments types.Object `tfsdk:"git_comments"`
381-
PreviewComments types.Bool `tfsdk:"preview_comments"`
382-
AutoAssignCustomDomains types.Bool `tfsdk:"auto_assign_custom_domains"`
383-
GitLFS types.Bool `tfsdk:"git_lfs"`
384-
FunctionFailover types.Bool `tfsdk:"function_failover"`
385-
CustomerSuccessCodeVisibility types.Bool `tfsdk:"customer_success_code_visibility"`
386-
GitForkProtection types.Bool `tfsdk:"git_fork_protection"`
387-
PrioritiseProductionBuilds types.Bool `tfsdk:"prioritise_production_builds"`
388-
DirectoryListing types.Bool `tfsdk:"directory_listing"`
389-
SkewProtection types.String `tfsdk:"skew_protection"`
390-
ResourceConfig *ResourceConfig `tfsdk:"resource_config"`
371+
BuildCommand types.String `tfsdk:"build_command"`
372+
DevCommand types.String `tfsdk:"dev_command"`
373+
Environment types.Set `tfsdk:"environment"`
374+
Framework types.String `tfsdk:"framework"`
375+
GitRepository *GitRepository `tfsdk:"git_repository"`
376+
ID types.String `tfsdk:"id"`
377+
IgnoreCommand types.String `tfsdk:"ignore_command"`
378+
InstallCommand types.String `tfsdk:"install_command"`
379+
Name types.String `tfsdk:"name"`
380+
OutputDirectory types.String `tfsdk:"output_directory"`
381+
PublicSource types.Bool `tfsdk:"public_source"`
382+
RootDirectory types.String `tfsdk:"root_directory"`
383+
ServerlessFunctionRegion types.String `tfsdk:"serverless_function_region"`
384+
TeamID types.String `tfsdk:"team_id"`
385+
VercelAuthentication *VercelAuthentication `tfsdk:"vercel_authentication"`
386+
PasswordProtection *PasswordProtection `tfsdk:"password_protection"`
387+
TrustedIps *TrustedIps `tfsdk:"trusted_ips"`
388+
OIDCTokenConfig *OIDCTokenConfig `tfsdk:"oidc_token_config"`
389+
OptionsAllowlist *OptionsAllowlist `tfsdk:"options_allowlist"`
390+
ProtectionBypassForAutomation types.Bool `tfsdk:"protection_bypass_for_automation"`
391+
ProtectionBypassForAutomationSecret types.String `tfsdk:"protection_bypass_for_automation_secret"`
392+
AutoExposeSystemEnvVars types.Bool `tfsdk:"automatically_expose_system_environment_variables"`
393+
GitComments types.Object `tfsdk:"git_comments"`
394+
PreviewComments types.Bool `tfsdk:"preview_comments"`
395+
AutoAssignCustomDomains types.Bool `tfsdk:"auto_assign_custom_domains"`
396+
GitLFS types.Bool `tfsdk:"git_lfs"`
397+
FunctionFailover types.Bool `tfsdk:"function_failover"`
398+
CustomerSuccessCodeVisibility types.Bool `tfsdk:"customer_success_code_visibility"`
399+
GitForkProtection types.Bool `tfsdk:"git_fork_protection"`
400+
PrioritiseProductionBuilds types.Bool `tfsdk:"prioritise_production_builds"`
401+
DirectoryListing types.Bool `tfsdk:"directory_listing"`
402+
SkewProtection types.String `tfsdk:"skew_protection"`
403+
ResourceConfig *ResourceConfig `tfsdk:"resource_config"`
391404
}
392405

393406
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
421434
DeploymentType: project.PasswordProtection.DeploymentType,
422435
}
423436
}
437+
424438
return ProjectDataSource{
425-
BuildCommand: project.BuildCommand,
426-
DevCommand: project.DevCommand,
427-
Environment: project.Environment,
428-
Framework: project.Framework,
429-
GitRepository: project.GitRepository,
430-
ID: project.ID,
431-
IgnoreCommand: project.IgnoreCommand,
432-
InstallCommand: project.InstallCommand,
433-
Name: project.Name,
434-
OutputDirectory: project.OutputDirectory,
435-
PublicSource: project.PublicSource,
436-
RootDirectory: project.RootDirectory,
437-
ServerlessFunctionRegion: project.ServerlessFunctionRegion,
438-
TeamID: project.TeamID,
439-
VercelAuthentication: project.VercelAuthentication,
440-
PasswordProtection: pp,
441-
TrustedIps: project.TrustedIps,
442-
OIDCTokenConfig: project.OIDCTokenConfig,
443-
OptionsAllowlist: project.OptionsAllowlist,
444-
AutoExposeSystemEnvVars: types.BoolPointerValue(response.AutoExposeSystemEnvVars),
445-
ProtectionBypassForAutomation: project.ProtectionBypassForAutomation,
446-
GitComments: project.GitComments,
447-
PreviewComments: project.PreviewComments,
448-
AutoAssignCustomDomains: project.AutoAssignCustomDomains,
449-
GitLFS: project.GitLFS,
450-
FunctionFailover: project.FunctionFailover,
451-
CustomerSuccessCodeVisibility: project.CustomerSuccessCodeVisibility,
452-
GitForkProtection: project.GitForkProtection,
453-
PrioritiseProductionBuilds: project.PrioritiseProductionBuilds,
454-
DirectoryListing: project.DirectoryListing,
455-
SkewProtection: project.SkewProtection,
456-
ResourceConfig: project.ResourceConfig,
439+
BuildCommand: project.BuildCommand,
440+
DevCommand: project.DevCommand,
441+
Environment: project.Environment,
442+
Framework: project.Framework,
443+
GitRepository: project.GitRepository,
444+
ID: project.ID,
445+
IgnoreCommand: project.IgnoreCommand,
446+
InstallCommand: project.InstallCommand,
447+
Name: project.Name,
448+
OutputDirectory: project.OutputDirectory,
449+
PublicSource: project.PublicSource,
450+
RootDirectory: project.RootDirectory,
451+
ServerlessFunctionRegion: project.ServerlessFunctionRegion,
452+
TeamID: project.TeamID,
453+
VercelAuthentication: project.VercelAuthentication,
454+
PasswordProtection: pp,
455+
TrustedIps: project.TrustedIps,
456+
OIDCTokenConfig: project.OIDCTokenConfig,
457+
OptionsAllowlist: project.OptionsAllowlist,
458+
AutoExposeSystemEnvVars: types.BoolPointerValue(response.AutoExposeSystemEnvVars),
459+
ProtectionBypassForAutomation: project.ProtectionBypassForAutomation,
460+
ProtectionBypassForAutomationSecret: project.ProtectionBypassForAutomationSecret,
461+
GitComments: project.GitComments,
462+
PreviewComments: project.PreviewComments,
463+
AutoAssignCustomDomains: project.AutoAssignCustomDomains,
464+
GitLFS: project.GitLFS,
465+
FunctionFailover: project.FunctionFailover,
466+
CustomerSuccessCodeVisibility: project.CustomerSuccessCodeVisibility,
467+
GitForkProtection: project.GitForkProtection,
468+
PrioritiseProductionBuilds: project.PrioritiseProductionBuilds,
469+
DirectoryListing: project.DirectoryListing,
470+
SkewProtection: project.SkewProtection,
471+
ResourceConfig: project.ResourceConfig,
457472
}, nil
458473
}
459474

vercel/resource_project.go

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -387,11 +387,20 @@ At this time you cannot use a Vercel Project resource with in-line ` + "`environ
387387
},
388388
"protection_bypass_for_automation": schema.BoolAttribute{
389389
Optional: true,
390-
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.",
390+
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.",
391391
},
392392
"protection_bypass_for_automation_secret": schema.StringAttribute{
393393
Computed: true,
394-
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.",
394+
Optional: true,
395+
Sensitive: true,
396+
Description: "If `protection_bypass_for_automation` is enabled, optionally set this value to specify a 32 character secret, otherwise a secret will be generated.",
397+
Validators: []validator.String{
398+
stringvalidator.RegexMatches(
399+
regexp.MustCompile(`^[a-zA-Z0-9]{32}$`),
400+
"Specify `generate` to have the value generated automatically, or specify a 32 character secret.",
401+
),
402+
validateAutomationBypassSecret(),
403+
},
395404
},
396405
"automatically_expose_system_environment_variables": schema.BoolAttribute{
397406
Optional: true,
@@ -1244,6 +1253,9 @@ func convertResponseToProject(ctx context.Context, response client.ProjectRespon
12441253
if !plan.ProtectionBypassForAutomation.IsNull() && !plan.ProtectionBypassForAutomation.ValueBool() {
12451254
protectionBypass = types.BoolValue(false)
12461255
}
1256+
if plan.ProtectionBypassForAutomationSecret.ValueString() != "" {
1257+
protectionBypassSecret = types.StringValue(plan.ProtectionBypassForAutomationSecret.ValueString())
1258+
}
12471259

12481260
environmentEntry := types.SetValueMust(envVariableElemType, env)
12491261
if plan.Environment.IsNull() {
@@ -1499,6 +1511,7 @@ func (r *projectResource) Create(ctx context.Context, req resource.CreateRequest
14991511
ProjectID: result.ID.ValueString(),
15001512
TeamID: result.TeamID.ValueString(),
15011513
NewValue: true,
1514+
Secret: plan.ProtectionBypassForAutomationSecret.ValueString(),
15021515
})
15031516
if err != nil {
15041517
resp.Diagnostics.AddError(
@@ -1778,11 +1791,15 @@ func (r *projectResource) Update(ctx context.Context, req resource.UpdateRequest
17781791
}
17791792

17801793
if state.ProtectionBypassForAutomation != plan.ProtectionBypassForAutomation {
1794+
secret := state.ProtectionBypassForAutomationSecret.ValueString()
1795+
if plan.ProtectionBypassForAutomationSecret.ValueString() != "" {
1796+
secret = plan.ProtectionBypassForAutomationSecret.ValueString()
1797+
}
17811798
_, err := r.client.UpdateProtectionBypassForAutomation(ctx, client.UpdateProtectionBypassForAutomationRequest{
17821799
ProjectID: plan.ID.ValueString(),
17831800
TeamID: plan.TeamID.ValueString(),
17841801
NewValue: plan.ProtectionBypassForAutomation.ValueBool(),
1785-
Secret: state.ProtectionBypassForAutomationSecret.ValueString(),
1802+
Secret: secret,
17861803
})
17871804
if err != nil {
17881805
resp.Diagnostics.AddError(

0 commit comments

Comments
 (0)