Skip to content

Add warning when expired_at attribute is null#1976

Open
sana-faraz wants to merge 9 commits intomainfrom
WarningWithExpiredAtNull
Open

Add warning when expired_at attribute is null#1976
sana-faraz wants to merge 9 commits intomainfrom
WarningWithExpiredAtNull

Conversation

@sana-faraz
Copy link

@sana-faraz sana-faraz commented Feb 23, 2026

Description

This change add a warning and a disclaimer message to the provider customer that if they create a token(tfe_team_token, tfe_organization_token or tfe_audit_trail_token) with no expiry_at attribute, its defaults to 2 years.

Remember to:

Testing plan

  1. Describe how to replicate : Create a resource of type tfe_team_token
  2. the conditions : tfe_team_token with no expiry_at or value null
  3. under which your code performs its purpose, : terraform plan should issue a warning that the token will expire in 24 months
  4. including example Terraform configs where necessary.
resource "tfe_team_token" "test_token" {
  team_id = tfe_team.team.id
}

External links

JIRA
RFC

@hashicorp-cla-app
Copy link

hashicorp-cla-app bot commented Feb 23, 2026

CLA assistant check
All committers have signed the CLA.

@hashicorp-cla-app
Copy link

CLA assistant check

Thank you for your submission! We require that all contributors sign our Contributor License Agreement ("CLA") before we can accept the contribution. Read and sign the agreement

Learn more about why HashiCorp requires a CLA and what the CLA includes

Have you signed the CLA already but the status is still pending? Recheck it.

@datadog-terraform-cloud-hashicorp
Copy link

datadog-terraform-cloud-hashicorp bot commented Feb 23, 2026

✅ Tests

🎉 All green!

❄️ No new flaky tests detected
🧪 All tests passed

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: f411e3d | Docs | Was this helpful? Give us feedback!

@sana-faraz sana-faraz marked this pull request as ready for review February 24, 2026 09:12
@sana-faraz sana-faraz requested a review from a team as a code owner February 24, 2026 09:12
Copy link

@debrin-hc debrin-hc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. I don't see any test cases in this PR. Can we add some for the resources we are changing?

Comment on lines +71 to +74
// Issue warning if expired_at is not provided
if _, ok := d.GetOk("expired_at"); !ok {
log.Printf("[WARN] The 'expired_at' attribute is not set for organization token. The token will default to an expiration of 24 months from creation. It is recommended to explicitly set an expiration date for security best practices.")
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Does this warning show up in the plan run output for an organization token? This seems to be adding a log message, instead of a "CLI output message".

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it shows up in the logs.. This uses the legacy SDK v2 plugin that why I added log.. Let me change it

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried ValidateFunc, ValidateDiagFunc.. Doesnt seem to work.. It might be a limitation in SDK v2?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is the output I see:

$ TF_LOG=warn terraform apply
╷
│ Warning: Provider development overrides are in effect
│
│ The following provider development overrides are set in the CLI configuration:
│  - hashicorp/tfe in /Users/bcroft/hashicorp/terraform-provider-tfe
│
│ The behavior may therefore not match any released version of the provider and applying changes may cause the state to become incompatible with
│ published releases.
╵
2026-02-25T11:31:54.730-0700 [WARN]  Provider "registry.terraform.io/hashicorp/tfe" produced an invalid plan for tfe_team.this, but we are tolerating it because it is using the legacy plugin SDK.
    The following problems may be the cause of any confusing errors from downstream operations:
      - .allow_member_token_management: planned value cty.True for a non-computed attribute
      - .organization_access: attribute representing nested block must not be unknown itself; set nested attribute values to unknown instead
2026-02-25T11:31:54.733-0700 [WARN]  provider.terraform-provider-tfe: Response contains warning diagnostic: @module=sdk.proto diagnostic_severity=WARNING tf_proto_version=6.10 tf_req_id=4027a5d6-3191-463e-9ba8-9bd17c93dd54 tf_resource_type=tfe_team_token diagnostic_detail="" diagnostic_summary="Team Token expiration null values defaults to 24 months" tf_provider_addr=registry.terraform.io/hashicorp/tfe tf_rpc=PlanResourceChange @caller=/Users/bcroft/go/pkg/mod/github.com/hashicorp/terraform-plugin-go@v0.29.0/tfprotov6/internal/diag/diagnostics.go:60 timestamp=2026-02-25T11:31:54.732-0700

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # tfe_team.this will be created
  + resource "tfe_team" "this" {
      + allow_member_token_management = true
      + id                            = (known after apply)
      + name                          = "test-team"
      + organization                  = "hashicorp"
      + visibility                    = (known after apply)

      + organization_access (known after apply)
    }

  # tfe_team_token.legacy will be created
  + resource "tfe_team_token" "legacy" {
      + id      = (known after apply)
      + team_id = (known after apply)
      + token   = (sensitive value)
    }

  # time_rotating.example will be created
  + resource "time_rotating" "example" {
      + day              = (known after apply)
      + hour             = (known after apply)
      + id               = (known after apply)
      + minute           = (known after apply)
      + month            = (known after apply)
      + rfc3339          = (known after apply)
      + rotation_days    = 29
      + rotation_rfc3339 = (known after apply)
      + second           = (known after apply)
      + unix             = (known after apply)
      + year             = (known after apply)
    }

Plan: 3 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + token = (sensitive value)
╷
│ Warning: Team Token expiration null values defaults to 24 months
│
│   with tfe_team_token.legacy,
│   on main.tf line 26, in resource "tfe_team_token" "legacy":
│   26: resource "tfe_team_token" "legacy" {
│
╵

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value:

I don't see this log, but I do see a log reflecting the warning diag

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are creating a team token that shows the warning because it uses the plugin framework but this log is for organization token..

}

func (m warnIfNullOnCreateModifier) PlanModifyString(ctx context.Context, req planmodifier.StringRequest, resp *planmodifier.StringResponse) {
if req.State.Raw.IsNull() && req.ConfigValue.IsNull() {
Copy link
Collaborator

@brandonc brandonc Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about just defaulting the value instead of weirdly coupling the message to the backend default (that is actually not known)

func (m *twoYearsModifier) PlanModifyString(_ context.Context, req planmodifier.StringRequest, resp *planmodifier.StringResponse) {
	// If the user explicitly set a value in their HCL config, do nothing.
	if !req.ConfigValue.IsNull() {
		return
	}

	resp.PlanValue = types.StringValue(time.Now().AddDate(2, 0, 0).Format(time.RFC3339))
}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Brandon,

We can either set default value during apply or allow the backend API to do so. Although both can be correct, we have implemented the backend API to accept null and calculate the expiry time making it the single source of truth.
We are fetching the expiredAt from the API response and storing it in the state file, also we have made expired_at as computable and UseStateForUnknown so the the customer explicitly knows that this value will be computed and will be available after apply.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As of now, is it no longer possible to create a non-expiring team token in HCPTF? It raises some tricky questions about provider stability

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants