- Notifications
You must be signed in to change notification settings - Fork6
Description
Summary
When a value used in a semaphoreui_project_environment secret resource is changing (rotated through another terraform provider, in my case a gitlab access token), the terraform plan is seeing the semaphoreui_project_environment update for the specific secret entry but the entry value is not updated properly after apply.
Versions
Semaphore server :v2.16.34-87a1c53-1760097739
Semaphore provider :cruglobal/semaphoreui v1.4.1
Terraform :v1.13.3
Terraform Tests
- Terraform snipet
resource "gitlab_personal_access_token" "this" { for_each = var.init_users_to_configure user_id = local.gitlab_users[each.key].id name = "${each.value.gitlab_user} personal access token" scopes = ["api", "read_api"] rotation_configuration = { expiration_days = "365" rotate_before_days = "15" } depends_on = [module.register_users]}...resource "semaphoreui_project_environment" "this" { for_each = local.semaphore_project_repositories project_id = each.value.project_id name = "${each.value.key}-repo${each.value.project_repository_id}-terraform-env-secrets" secrets = [ { name = "AWS_ACCESS_KEY_ID" value = var.aws_access_key_id type = "env" }, { name = "AWS_SECRET_ACCESS_KEY" value = var.aws_secret_access_id type = "env" }, { name = "GITLAB_TOKEN_ADMIN" value = var.gitlab_token type = "env" }, { name = "GITLAB_TOKEN_USER" value = gitlab_personal_access_token.this[each.value.key].token type = "env" }, { name = "SEMAPHORE_API_TOKEN" value = var.semaphore_api_token type = "env" }, { name = "VAULT_TOKEN" value = var.vault_token type = "env" }, { name = "VAULT_APPROLE_ROLE_ID" value = module.register_users.approles_role_id[format("%s-%s", each.value.key, each.value.environment)] type = "env" }, { name = "VAULT_APPROLE_SECRET_ID" value = module.register_users.approles_secret_id[format("%s-%s", each.value.key, each.value.environment)] type = "env" }, { # sshkeys also added in env secrets because of bash/ansible only use it for initial checkout name = "SSH_KEYS_GITLAB" value = module.register_users.user_gitlab_keys[each.value.key] type = "env" }, { name = "SSH_KEYS_SERVER" value = module.register_users.user_server_keys[format("%s-%s", each.value.key, each.value.environment)] type = "env" } ]}- Terraform plan
08:55:47.800 STDOUT terraform: Terraform will perform the following actions:08:55:47.800 STDOUT terraform: # gitlab_personal_access_token.this["user"] will be updated in-place08:55:47.800 STDOUT terraform: ~ resource "gitlab_personal_access_token" "this" {08:55:47.800 STDOUT terraform: ~ active = true -> (known after apply)08:55:47.800 STDOUT terraform: ~ created_at = "2025-10-02 13:45:34.119 +0000 UTC" -> (known after apply)08:55:47.800 STDOUT terraform: ~ id = "263:283" -> (known after apply)08:55:47.800 STDOUT terraform: name = "user-gitops personal access token"08:55:47.800 STDOUT terraform: ~ revoked = false -> (known after apply)08:55:47.800 STDOUT terraform: ~ rotation_configuration = {08:55:47.800 STDOUT terraform: ~ rotate_before_days = 365 -> 1008:55:47.800 STDOUT terraform: # (1 unchanged attribute hidden)08:55:47.801 STDOUT terraform: }08:55:47.801 STDOUT terraform: ~ token = (sensitive value)08:55:47.801 STDOUT terraform: + validate_past_expiration_date = false08:55:47.801 STDOUT terraform: # (4 unchanged attributes hidden)08:55:47.801 STDOUT terraform: }08:55:47.801 STDOUT terraform: # semaphoreui_project_environment.this["user-0"] will be updated in-place08:55:47.801 STDOUT terraform: ~ resource "semaphoreui_project_environment" "this" {08:55:47.801 STDOUT terraform: id = 13408:55:47.801 STDOUT terraform: name = "user-repo23-terraform-env-secrets"08:55:47.801 STDOUT terraform: ~ secrets = [08:55:47.801 STDOUT terraform: ~ {08:55:47.801 STDOUT terraform: id = 51708:55:47.801 STDOUT terraform: name = "GITLAB_TOKEN_USER"08:55:47.801 STDOUT terraform: ~ value = (sensitive value)08:55:47.801 STDOUT terraform: # (1 unchanged attribute hidden)08:55:47.801 STDOUT terraform: },08:55:47.801 STDOUT terraform: # (9 unchanged elements hidden)08:55:47.801 STDOUT terraform: ]08:55:47.801 STDOUT terraform: # (1 unchanged attribute hidden)08:55:47.801 STDOUT terraform: }- Terraform apply
08:58:19.861 STDOUT terraform: gitlab_personal_access_token.this["user"]: Modifying... [id=263:283]08:58:20.000 STDOUT terraform: gitlab_personal_access_token.this["user"]: Modifications complete after 0s [id=263:314]08:58:20.199 STDOUT terraform: semaphoreui_project_environment.this["user-0"]: Modifying... [name=user-repo23-terraform-env-secrets]08:58:20.204 INFO terraform: TF_LOG: Starting apply for semaphoreui_project_environment.this["user-0"]08:58:20.632 STDOUT terraform: semaphoreui_project_environment.this["user-0"]: Modifications complete after 1s [name=user-repo23-terraform-env-secrets]08:58:20.817 INFO terraform: TF_LOG: provider: plugin process exited: plugin=.terraform/providers/registry.terraform.io/cruglobal/semaphoreui/1.4.1/linux_amd64/terraform-provider-semaphoreui_v1.4.1 id=489154Expected Behavior
I was expecting the environment secret entryGITLAB_TOKEN_USER to be updated with the new gitlab token value but it's not.
The same secret update execute through the Semaphore API is working as expected
curl -X 'PUT' \ 'https://semaphoreui-mysite.com/api/project/12/environment/134' \ -H 'accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "id": 134, "name": "user-repo23-terraform-env-secrets", "project_id": 12, "password": null, "json": "{}", "env": "{}", "secrets": [ { "id": 517, "name": "GITLAB_TOKEN_USER", "secret": "glpat-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "type": "env", "operation": "update" } ]}'The env secret entry GITLAB_TOKEN_USER is well updated
More tests on the provider api calls
I'm not fluent in go and decided to intercept the provider API calls (using mitmproxy) to check the sent payload during that terraform environment secret update.
It seems that no secret values are sent in the JSON payload when the provider is trying to update an environment secret value.
PUT REQUEST
PUT /api/project/12/environment/134 HTTP/1.1Host: semaphoreui-mysite.com:443User-Agent: Go-http-client/1.1Content-Length: 649Accept: application/jsonAccept: text/plain; charset=utf-8Authorization: Bearer h0tzaayu_8h8gd8ogg5wgdzopwlk9ozu-ozmif8qsqu=Content-Type: application/jsonAccept-Encoding: gzip{"env":"{}","id":134,"json":"{}","name":"user-repo23-terraform-env-secrets","project_id":12,"secrets":[{"id":514,"name":"AWS_ACCESS_KEY_ID","type":"env"},{"id":515,"name":"AWS_SECRET_ACCESS_KEY","type":"env"},{"id":516,"name":"GITLAB_TOKEN_ADMIN","type":"env"},{"id":517,"name":"GITLAB_TOKEN_USER","operation":"update","type":"env"},{"id":518,"name":"SEMAPHORE_API_TOKEN","type":"env"},{"id":519,"name":"VAULT_TOKEN","type":"env"},{"id":520,"name":"VAULT_APPROLE_ROLE_ID","type":"env"},{"id":521,"name":"VAULT_APPROLE_SECRET_ID","type":"env"},{"id":522,"name":"SSH_KEYS_GITLAB","type":"env"},{"id":523,"name":"SSH_KEYS_SERVER","type":"env"}]}PUT RESPONSE
HTTP/1.1 204 No ContentContent-Type: application/jsonDate: Fri, 24 Oct 2025 11:01:17 GMTSo I'm wondering is it intentional ?
in any case this is very annoying for the life cycle management of these secrets also stored in Semaphore environment secrets