-
Notifications
You must be signed in to change notification settings - Fork 32
Description
When setting protection_bypass_for_automation
and protection_bypass_for_automation_secret
through vercel_project
, the value is correctly updated in the terraform state, but not in the actual project as confirmed through the UI.
code:
# Vercel Protection Bypass for Automation requires the secret to be exactly 32
# characters long, and only if we inject the value can we also use it elsewhere,
# e.g. to put it into 1password for Github Actions.
resource "random_password" "vercel_automation_bypass" {
count = var.terraform_env_name == "dogfood" ? 1 : 0
length = 32
special = false # vercel does not like special characters
}
# Configure Protection Bypass for Automation on the project. This is only done
# in dogfood, as we primarily use vercel for code review deployments on PRs.
resource "vercel_project" "frontend" {
count = var.terraform_env_name == "dogfood" ? 1 : 0
name = "frontend"
team_id = var.vercel_team_id
enable_affected_projects_deployments = true
framework = "nextjs"
git_repository = {
type = "github"
repo = "overmindtech/workspace"
production_branch = "main"
}
protection_bypass_for_automation = true
protection_bypass_for_automation_secret = random_password.vercel_automation_bypass[0].result
root_directory = "frontend"
skew_protection = "12 hours"
}
resource "onepassword_item" "vercel_generated" {
count = var.terraform_env_name == "dogfood" ? 1 : 0
vault = data.onepassword_vault.global_vault.uuid
title = "vercel"
category = "secure_note"
note_value = "generated items from vercel; provisioned through the dogfood terraform environment"
section {
label = "generated"
field {
label = "info: VERCEL_AUTOMATION_BYPASS_SECRET"
type = "STRING"
value = "https://vercel.com/overmindtech/frontend/settings/deployment-protection; this is provisioned from terraform"
}
field {
label = "VERCEL_AUTOMATION_BYPASS_SECRET"
type = "CONCEALED"
value = random_password.vercel_automation_bypass[0].result
}
}
}
plan:
[...]
vercel_project.frontend[0]: Refreshing state... [id=prj_pobSoGaGRB9xUIAp3ckLPNRvWMsM]
[...]
# random_password.vercel_automation_bypass[0] is tainted, so must be replaced
-/+ resource "random_password" "vercel_automation_bypass" {
~ bcrypt_hash = (sensitive value)
~ id = "none" -> (known after apply)
~ result = (sensitive value)
# (10 unchanged attributes hidden)
}
[...]
# vercel_project.frontend[0] will be updated in-place
~ resource "vercel_project" "frontend" {
id = "prj_pobSoGaGRB9xUIAp3ckLPNRvWMsM"
name = "frontend"
~ protection_bypass_for_automation_secret = (sensitive value)
# (20 unchanged attributes hidden)
}
[...]
# onepassword_item.vercel_generated[0] will be updated in-place
~ resource "onepassword_item" "vercel_generated" {
id = "vaults/smyzrf7ekx2hlq7oq6kntecca4/items/qektdrtygrybtjecadu7777hjy"
+ password = (sensitive value)
# (5 unchanged attributes hidden)
~ section {
id = "74443c7f-eb6b-4ecf-83ab-52e2c279eb83"
# (1 unchanged attribute hidden)
~ field {
id = "xwjdroeux4bqkaz2hgnta5vaqu"
~ value = (sensitive value)
# (2 unchanged attributes hidden)
}
# (1 unchanged block hidden)
}
}
apply:
random_password.vercel_automation_bypass[0]: Destroying... [id=none]
random_password.vercel_automation_bypass[0]: Destruction complete after 0s
random_password.vercel_automation_bypass[0]: Creating...
random_password.vercel_automation_bypass[0]: Creation complete after 0s [id=none]
onepassword_item.vercel_generated[0]: Modifying... [id=vaults/smyzrf7ekx2hlq7oq6kntecca4/items/qektdrtygrybtjecadu7777hjy]
vercel_project.frontend[0]: Modifying... [id=prj_pobSoGaGRB9xUIAp3ckLPNRvWMsM]
onepassword_item.vercel_generated[0]: Modifications complete after 1s [id=vaults/smyzrf7ekx2hlq7oq6kntecca4/items/qektdrtygrybtjecadu7777hjy]
vercel_project.frontend[0]: Modifications complete after 1s [id=prj_pobSoGaGRB9xUIAp3ckLPNRvWMsM]
[...]
Apply complete! Resources: 26 added, 8 changed, 2 destroyed.
Checking the new state:
terraform plan -out=tfplan
terraform show -json tfplan 2>&1 | jq | less
Searching for random_password.vercel_automation_bypass
and vercel_project.frontend
in the JSON output shows the same value as stored in 1password (proving that the value has been correctly applied outside) on both random_password.vercel_automation_bypass.result
(the generated value) as well as on vercel_project.frontend[0].protection_bypass_for_automation_secret
(proving that the value has been correctly passed to the vercel_project provider).
Reading through the client code at
terraform-provider-vercel/client/project_protection_bypass_for_automation_update.go
Lines 26 to 48 in 1d1292b
func getUpdateBypassProtectionRequestBody(newValue bool, secret string) string { | |
if newValue { | |
if secret == "" { | |
return "{}" | |
} | |
return string(mustMarshal(struct { | |
Revoke generateBypassProtectionRequest `json:"generate"` | |
}{ | |
Revoke: generateBypassProtectionRequest{ | |
Secret: secret, | |
}, | |
})) | |
} | |
return string(mustMarshal(struct { | |
Revoke revokeBypassProtectionRequest `json:"revoke"` | |
}{ | |
Revoke: revokeBypassProtectionRequest{ | |
Regenerate: false, | |
Secret: secret, | |
}, | |
})) | |
} |
func getUpdateBypassProtectionRequestBody(newValue bool, secret string) string {
if newValue {
if secret == "" {
return "{}"
}
return string(mustMarshal(struct {
Generate generateBypassProtectionRequest `json:"generate"`
}{
Generate: generateBypassProtectionRequest{
Secret: secret,
},
}))
}
return string(mustMarshal(struct {
Revoke revokeBypassProtectionRequest `json:"revoke"`
}{
Revoke: revokeBypassProtectionRequest{
Regenerate: false,
Secret: secret,
},
}))
}
instead, but that's just a red herring that had me chasing my tail for 10 minutes.
The true error is that
if state.ProtectionBypassForAutomation != plan.ProtectionBypassForAutomation { |
ProtectionBypassForAutomation
flag has been toggled, but not if the secret is still the same.