Skip to content

Make Terraform reject empty strings as invalid workspace names #37267

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 26, 2025

Conversation

SarahFrench
Copy link
Member

@SarahFrench SarahFrench commented Jun 23, 2025

Handling a workspace called "" is currently disallowed due to how individual backends are implemented. This PR formalises making this an invalid thing for a user to do by changing validation logic to reject "" as a workspace name. This validation logic is currently used in terraform workspace select and terraform workspace new commands.

Relevant info

Some backends explicitly block ""

Here is code where backend implementations block "" at the point of calling code trying to obtain a state manager for a given workspace name:

  • s3 - "" triggers a missing state name error
  • gcs - "" triggers a is not a valid state name error
  • kubernetes - "" triggers a missing state name error

Some backends don't block ""

Before opening this for review I'm going to ask around about whether an empty string could be valid for some backends. My hunch is that this is just missing validation, but I want to confirm.

Workspace"" can be equivalent to workspace "default"

For some backend the "" workspace is handled like the "default" workspace. For example, the local backend creates state in the default location when the "" workspace is selected.

Target Release

1.13.x

Rollback Plan

  • If a change needs to be reverted, we will roll out an update to the code within 7 days.

Changes to Security Controls

Are there any changes to security controls (access controls, encryption, logging) in this pull request? If so, explain.

CHANGELOG entry

  • This change is user-facing and I added a changelog entry.
  • This change is not user-facing.

@SarahFrench SarahFrench marked this pull request as ready for review June 23, 2025 16:26
@SarahFrench SarahFrench requested a review from a team as a code owner June 23, 2025 16:26
@SarahFrench
Copy link
Member Author

SarahFrench commented Jun 23, 2025

Opening this for review, but I'm waiting to hear back from the Azure team about whether an empty string workspace could be used with their backend (i.e. would a user experience an API error when trying to do it, or not) Edit: see investigation below.

Their response would inform a wider discussion I think needs to be had in this PR: is adding this validation something we'd consider a breaking change, and therefore something that we'd not want to merge?

@radeksimko
Copy link
Member

The situation with the AzureRM backend is slightly weird but mostly good in the context of this PR.

I was able to go through terraform workspace new "", which did result in creation of a file called terraform.tfstateenv: in the blob store.

$ terraform workspace new ""
Created and switched to workspace ""!

You're now on a new, empty workspace. Workspaces isolate their state,
so if you run "terraform plan" Terraform will not see any existing state
for this configuration.

I'm unsure why the backend uses file suffixes with colons as a way to separate workspaces but for the purpose of this test I just accept that design decision. 🤷🏻‍♂️

The "good" part is that while terraform select "" was "successful" in the sense that return code was 0 and output Switched to workspace ""., the workspace actually selected was always the default one, as proven via terraform workspace list:

* default
  

Relatedly, running apply resulted in state being stored in the default workspace.

TL;DR while creation of workspace called "" is possible, it seems impossible to use it for any purpose.

Therefore I would conclude that the validation/rejection on Core side is net positive for Azure users as it avoids the confusing UX.

@SarahFrench
Copy link
Member Author

I've seen the same behaviour when testing the pg backend. Creating and switching to a new "" workspace creates a row in the table (pg backend uses a single table where theres a record per workspace) that has an empty state, but if you run a terraform apply then Terraform will either use a prexisting or create a new default record to save the new state to:

I performed an apply in the default workspace:

terraform_backend=# SELECT * FROM terraform_remote_state.states;
-[ RECORD 1 ]-------------------------------------------------------------------
id   | 1
name | default
data | {                                                                        +
     |   "version": 4,                                                          +
     |   "terraform_version": "1.13.0",                                         +
     |   "serial": 1,                                                           +
     |   "lineage": "e726b6db-1a5b-8ccf-89b7-dfa1e3e83684",                     +
     |   "outputs": {},                                                         +
     |   "resources": [                                                         +
     |     {                                                                    +
     |       "mode": "managed",                                                 +
     |       "type": "random_pet",                                              +
     |       "name": "my_pet",                                                  +
     |       "provider": "provider[\"registry.terraform.io/hashicorp/random\"]",+
     |       "instances": [                                                     +
     |         {                                                                +
     |           "schema_version": 0,                                           +
     |           "attributes": {                                                +
     |             "id": "eternal-bulldog",                                     +
     |             "keepers": null,                                             +
     |             "length": 2,                                                 +
     |             "prefix": null,                                              +
     |             "separator": "-"                                             +
     |           },                                                             +
     |           "sensitive_attributes": [],                                    +
     |           "identity_schema_version": 0                                   +
     |         }                                                                +
     |       ]                                                                  +
     |     }                                                                    +
     |   ],                                                                     +
     |   "check_results": null                                                  +
     | }                                                                        +
     | 

After terraform workspace new "" and terraform apply I see this, which shows the default state is being used:

Screenshot 2025-06-26 at 12 02 50

However an empty state was made as a consequence of the workspace new command:

-[ RECORD 2]-------------------------------------------------------------------
id   | 2
name | 
data | {                                                                        +
     |   "version": 4,                                                          +
     |   "terraform_version": "1.13.0",                                         +
     |   "serial": 1,                                                           +
     |   "lineage": "753e583f-88d6-da98-8218-049fc2c1c560",                     +
     |   "outputs": {},                                                         +
     |   "resources": [],                                                       +
     |   "check_results": null                                                  +
     | }                                                                        +
     | 

When I deleted the default state from the table and re-ran the apply with workspace "" selected it created a new default workspace (note that id = 3 here):

-[ RECORD 1 ]-------------------------------------------------------------------
id   | 2
name | 
data | {                                                                        +
     |   "version": 4,                                                          +
     |   "terraform_version": "1.13.0",                                         +
     |   "serial": 1,                                                           +
     |   "lineage": "753e583f-88d6-da98-8218-049fc2c1c560",                     +
     |   "outputs": {},                                                         +
     |   "resources": [],                                                       +
     |   "check_results": null                                                  +
     | }                                                                        +
     | 
-[ RECORD 2 ]-------------------------------------------------------------------
id   | 3
name | default
data | {                                                                        +
     |   "version": 4,                                                          +
     |   "terraform_version": "1.13.0",                                         +
     |   "serial": 1,                                                           +
     |   "lineage": "489cd9d2-9557-d335-d044-95c5bf81195d",                     +
     |   "outputs": {},                                                         +
     |   "resources": [                                                         +
     |     {                                                                    +
     |       "mode": "managed",                                                 +
     |       "type": "random_pet",                                              +
     |       "name": "my_pet",                                                  +
     |       "provider": "provider[\"registry.terraform.io/hashicorp/random\"]",+
     |       "instances": [                                                     +
     |         {                                                                +
     |           "schema_version": 0,                                           +
     |           "attributes": {                                                +
     |             "id": "real-kit",                                            +
     |             "keepers": null,                                             +
     |             "length": 2,                                                 +
     |             "prefix": null,                                              +
     |             "separator": "-"                                             +
     |           },                                                             +
     |           "sensitive_attributes": [],                                    +
     |           "identity_schema_version": 0                                   +
     |         }                                                                +
     |       ]                                                                  +
     |     }                                                                    +
     |   ],                                                                     +
     |   "check_results": null                                                  +
     | }                                                                        +
     | 

@SarahFrench
Copy link
Member Author

SarahFrench commented Jun 26, 2025

I think given we've seen that the "" workspace isn't actually usable in these 2 backends that allow it to be created, I'm happy that adding this extra validation wouldn't impact any users' existing state.

Edit: @radeksimko I've requested you as a reviewer as you've got context.

@SarahFrench SarahFrench requested a review from radeksimko June 26, 2025 11:07
@SarahFrench SarahFrench merged commit 9212a2e into main Jun 26, 2025
17 of 18 checks passed
@SarahFrench SarahFrench deleted the pss/empty-string-invalid-workspace branch June 26, 2025 11:27
Copy link
Contributor

I'm going to lock this pull request because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active contributions.
If you have found a problem that seems related to this change, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jul 27, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants