From 8516771d15559c19c16cac7f675103c7c1a395c0 Mon Sep 17 00:00:00 2001 From: rafcio19 Date: Fri, 12 May 2023 11:10:52 +0100 Subject: [PATCH] Secrets: add NextRotationDate and LastRotatedDate to secrets (#6313) --- moto/secretsmanager/models.py | 11 ++++- .../test_secretsmanager.py | 42 ++++++++++++++----- 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/moto/secretsmanager/models.py b/moto/secretsmanager/models.py index bb492c4ab..53d049ef0 100644 --- a/moto/secretsmanager/models.py +++ b/moto/secretsmanager/models.py @@ -88,6 +88,8 @@ class FakeSecret: self.auto_rotate_after_days = 0 self.deleted_date: Optional[float] = None self.policy: Optional[str] = None + self.next_rotation_date: Optional[int] = None + self.last_rotation_date: Optional[int] = None def update( self, @@ -167,9 +169,10 @@ class FakeSecret: "RotationEnabled": self.rotation_enabled, "RotationLambdaARN": self.rotation_lambda_arn, "RotationRules": {"AutomaticallyAfterDays": self.auto_rotate_after_days}, - "LastRotatedDate": None, + "LastRotatedDate": self.last_rotation_date, "LastChangedDate": self.last_changed_date, "LastAccessedDate": None, + "NextRotationDate": self.next_rotation_date, "DeletedDate": self.deleted_date, "Tags": self.tags, "VersionIdsToStages": version_id_to_stages, @@ -535,6 +538,10 @@ class SecretsManagerBackend(BaseBackend): ) raise InvalidParameterException(msg) + self.secrets[secret_id].next_rotation_date = int(time.time()) + ( + int(rotation_period) * 86400 + ) + secret = self.secrets[secret_id] # The rotation function must end with the versions of the secret in @@ -625,7 +632,7 @@ class SecretsManagerBackend(BaseBackend): secret.versions[new_version_id], new_version_id ) secret.versions[new_version_id]["version_stages"] = ["AWSCURRENT"] - + self.secrets[secret_id].last_rotation_date = int(time.time()) return secret.to_short_dict() def get_random_password( diff --git a/tests/test_secretsmanager/test_secretsmanager.py b/tests/test_secretsmanager/test_secretsmanager.py index 6eee8b762..f2f78ec22 100644 --- a/tests/test_secretsmanager/test_secretsmanager.py +++ b/tests/test_secretsmanager/test_secretsmanager.py @@ -711,21 +711,41 @@ def test_cancel_rotate_secret(): @mock_secretsmanager def test_rotate_secret(): - conn = boto3.client("secretsmanager", region_name="us-west-2") - conn.create_secret( - Name=DEFAULT_SECRET_NAME, SecretString="foosecret", Description="foodescription" - ) + # Setup + frozen_time = datetime(2023, 5, 20, 10, 20, 30, tzinfo=tzlocal()) + rotate_after_days = 10 + with freeze_time(frozen_time): + conn = boto3.client("secretsmanager", region_name="us-west-2") + conn.create_secret( + Name=DEFAULT_SECRET_NAME, + SecretString="foosecret", + Description="foodescription", + ) - rotated_secret = conn.rotate_secret(SecretId=DEFAULT_SECRET_NAME) + # Execute + rotated_secret = conn.rotate_secret( + SecretId=DEFAULT_SECRET_NAME, + RotationRules={"AutomaticallyAfterDays": rotate_after_days}, + ) + describe_secret = conn.describe_secret(SecretId=DEFAULT_SECRET_NAME) - assert rotated_secret - assert rotated_secret["ARN"] != "" # Test arn not empty - assert rotated_secret["Name"] == DEFAULT_SECRET_NAME - assert rotated_secret["VersionId"] != "" + # Verify + assert rotated_secret + assert rotated_secret["ARN"] != "" # Test arn not empty + assert rotated_secret["Name"] == DEFAULT_SECRET_NAME + assert rotated_secret["VersionId"] != "" + assert describe_secret["Description"] == "foodescription" + assert "NextRotationDate" in describe_secret + assert "LastRotatedDate" in describe_secret - describe_secret = conn.describe_secret(SecretId=DEFAULT_SECRET_NAME) + # can't do freeze time tests in servermode tests + if settings.TEST_SERVER_MODE: + return - assert describe_secret["Description"] == "foodescription" + assert describe_secret["LastChangedDate"] == frozen_time + assert describe_secret["NextRotationDate"] == frozen_time + timedelta( + days=rotate_after_days + ) @mock_secretsmanager