hashicorp / terraform-provider-time

Utility provider that provides Time-Based Resources
https://registry.terraform.io/providers/hashicorp/time/latest
Mozilla Public License 2.0
96 stars 28 forks source link

drift in `time_rotating` making periodic applies unusable #195

Open faultymonk opened 1 year ago

faultymonk commented 1 year ago

Terraform CLI and Provider Versions

Terraform v1.3.7 on darwin_amd64

Use Cases or Problem Statement

Currently, when the time_rotating resource rotates, it recreates with time at apply plus rotation interval as described from the docs.

This rotation only occurs when Terraform is executed, meaning there will be drift between the rotation timestamp and actual rotation. The new rotation timestamp offset includes this drift.

For the use case where applies are cron'ed using the same rotation period, it leads to a situation where rotation cannot work properly.

  1. If the apply happens before rotation_rfc3339, nothing happens as expected.
  2. If the apply happens after rotation_rfc3339, the new rotation_rfc3339 is created with the additional time drift added.

The effect with cron'ed applies with the same rotation period means if 1 happens, it won't rotate until the next cron'ed apply (which would be roughly double the desired rotation period).

If 2 happens, due to the additional time drift being added, 1 is likely to happen again. And no matter what periodic delay is added to the cron'ed time, this drift will continually happen making the rotation at the same time during the day impossible.

As an example, if a daily rotation at 00:05 is desired and time_rotating is initially imported w/ 00:00 & a rotation period of 24h. First rotation would proceed as expected, but rotation_rfc3339 would now be 00:05 + 24h. Second rotation, if it happened just slightly before 00:05, would not rotate due to the lack of expiration & will not be rotated until the next day. If there's any drift on the next apply, rotation_rfc3339 will drift further and further from the desired expiration time at 00:00.

Proposal

Add an optional ignore_drift parameter. This parameter would cause time_rotating to use the previous rotation_rfc3339 time and append the rotation period to it. This would allow cron'ed rotations to always happen after the rotating period and ensure that the time_rotating replace is always replaced.

Only in the case that the previous rotation_rfc3339 + rotation period is before the current time at apply, that the previous rotation_rfc3339 should be discarded and the current time at apply is used.

How much impact is this issue causing?

High

Additional Information

No response

Code of Conduct

Matthijsy commented 5 months ago

Isn't this easily achievable by doing something like this? I am having the same issue at the moment and consider using this

resource "time_rotating" "secrets" {
  rfc3339 = "${formatdate("YYYY-MM-DD", timestamp())}T18:00:00Z"
  rotation_days = 2
}
muru commented 2 weeks ago

Instead of an ignore_drift that ignores a gap after rotation_rfc3339, what I'd like is a grace period setting that starts triggering rotation some N time units before rotation_rfc3339. So if a token is to expire at, say, 90 days, I'd like it to start offering to rotate, say, 85 days. If the rotation happens instead after 90 days, when the token has already expired, then whichever service uses it will have downtime.

Currently I'm using something like:

local {
  expiration   = 90
  grace_period = 5
}

resource "time_rotating" "grace" {
  rotation_days = local.expiration - local.grace
}

resource "time_offset" "expiration" {
  offset_days = local.grace
  triggers = {
    grace_period = time_rotating.grace.rotation_rfc3339
  }
}

resource something_that_expires like_a_token {
  # ...
  expiration = time_offset.expiration.rfc3339
}

Then if I schedule a Terraform apply at, say, every 88 days (or any time between 85 and 90 days), this should continue to work fine. It would be nicer if the time_rotating resource provided this as a built-in feature.