Add CreatedDate and LastChangedDate in secretsmanager responses (#4770)

This commit is contained in:
Daniel Fangl 2022-01-25 11:24:26 +01:00 committed by GitHub
parent 54c7fd5e91
commit 3f534119f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 64 additions and 4 deletions

View File

@ -61,6 +61,8 @@ class FakeSecret:
kms_key_id=None,
version_id=None,
version_stages=None,
last_changed_date=None,
created_date=None,
):
self.secret_id = secret_id
self.name = secret_id
@ -72,14 +74,20 @@ class FakeSecret:
self.kms_key_id = kms_key_id
self.version_id = version_id
self.version_stages = version_stages
self.last_changed_date = last_changed_date
self.created_date = created_date
self.rotation_enabled = False
self.rotation_lambda_arn = ""
self.auto_rotate_after_days = 0
self.deleted_date = None
def update(self, description=None, tags=None, kms_key_id=None):
def update(
self, description=None, tags=None, kms_key_id=None, last_changed_date=None
):
self.description = description
self.tags = tags or []
if last_changed_date is not None:
self.last_changed_date = last_changed_date
if kms_key_id is not None:
self.kms_key_id = kms_key_id
@ -134,12 +142,13 @@ class FakeSecret:
"RotationLambdaARN": self.rotation_lambda_arn,
"RotationRules": {"AutomaticallyAfterDays": self.auto_rotate_after_days},
"LastRotatedDate": None,
"LastChangedDate": None,
"LastChangedDate": self.last_changed_date,
"LastAccessedDate": None,
"DeletedDate": self.deleted_date,
"Tags": self.tags,
"VersionIdsToStages": version_id_to_stages,
"SecretVersionsToStages": version_id_to_stages,
"CreatedDate": self.created_date,
}
def _form_version_ids_to_stages(self):
@ -350,10 +359,11 @@ class SecretsManagerBackend(BaseBackend):
if secret_binary is not None:
secret_version["secret_binary"] = secret_binary
update_time = int(time.time())
if secret_id in self.secrets:
secret = self.secrets[secret_id]
secret.update(description, tags, kms_key_id)
secret.update(description, tags, kms_key_id, last_changed_date=update_time)
if "AWSPENDING" in version_stages:
secret.versions[version_id] = secret_version
@ -368,6 +378,8 @@ class SecretsManagerBackend(BaseBackend):
description=description,
tags=tags,
kms_key_id=kms_key_id,
last_changed_date=update_time,
created_date=update_time,
)
secret.set_versions({version_id: secret_version})
secret.set_default_version_id(version_id)

View File

@ -1,5 +1,8 @@
# -*- coding: utf-8 -*-
from datetime import datetime
import boto3
from dateutil.tz import tzlocal
from moto import mock_secretsmanager
from botocore.exceptions import ClientError
@ -41,6 +44,10 @@ def test_list_secrets():
assert secrets["SecretList"][1]["Name"] == "test-secret-2"
assert secrets["SecretList"][1]["Tags"] == [{"Key": "a", "Value": "1"}]
assert secrets["SecretList"][1]["SecretVersionsToStages"] is not None
assert secrets["SecretList"][0]["CreatedDate"] <= datetime.now(tz=tzlocal())
assert secrets["SecretList"][1]["CreatedDate"] <= datetime.now(tz=tzlocal())
assert secrets["SecretList"][0]["LastChangedDate"] <= datetime.now(tz=tzlocal())
assert secrets["SecretList"][1]["LastChangedDate"] <= datetime.now(tz=tzlocal())
@mock_secretsmanager

View File

@ -1,11 +1,15 @@
import os
import boto3
from dateutil.tz import tzlocal
from moto import mock_secretsmanager, mock_lambda, settings
from moto.core import ACCOUNT_ID
from botocore.exceptions import ClientError, ParamValidationError
import string
import pytz
from datetime import datetime
from freezegun import freeze_time
from datetime import timedelta, datetime
import sure # noqa # pylint: disable=unused-import
from uuid import uuid4
import pytest
@ -430,6 +434,14 @@ def test_describe_secret():
assert secret_description["ARN"] != "" # Test arn not empty
assert secret_description_2["Name"] == ("test-secret-2")
assert secret_description_2["ARN"] != "" # Test arn not empty
assert secret_description["CreatedDate"] <= datetime.now(tz=tzlocal())
assert secret_description["CreatedDate"] > datetime.fromtimestamp(1, pytz.utc)
assert secret_description_2["CreatedDate"] <= datetime.now(tz=tzlocal())
assert secret_description_2["CreatedDate"] > datetime.fromtimestamp(1, pytz.utc)
assert secret_description["LastChangedDate"] <= datetime.now(tz=tzlocal())
assert secret_description["LastChangedDate"] > datetime.fromtimestamp(1, pytz.utc)
assert secret_description_2["LastChangedDate"] <= datetime.now(tz=tzlocal())
assert secret_description_2["LastChangedDate"] > datetime.fromtimestamp(1, pytz.utc)
@mock_secretsmanager
@ -967,6 +979,35 @@ def test_update_secret(pass_arn):
assert created_secret["VersionId"] != updated_secret["VersionId"]
@mock_secretsmanager
@pytest.mark.parametrize("pass_arn", [True, False])
def test_update_secret_updates_last_changed_dates(pass_arn):
conn = boto3.client("secretsmanager", region_name="us-west-2")
# create a secret
created_secret = conn.create_secret(Name="test-secret", SecretString="foosecret")
secret_id = created_secret["ARN"] if pass_arn else "test-secret"
# save details for secret before modification
secret_details_1 = conn.describe_secret(SecretId=secret_id)
# check if only LastChangedDate changed, CreatedDate should stay the same
with freeze_time(timedelta(minutes=1)):
conn.update_secret(SecretId="test-secret", Description="new-desc")
secret_details_2 = conn.describe_secret(SecretId=secret_id)
assert secret_details_1["CreatedDate"] == secret_details_2["CreatedDate"]
if os.environ.get("TEST_SERVER_MODE", "false").lower() == "false":
assert (
secret_details_1["LastChangedDate"]
< secret_details_2["LastChangedDate"]
)
else:
# Can't manipulate time in server mode, so use weaker constraints here
assert (
secret_details_1["LastChangedDate"]
<= secret_details_2["LastChangedDate"]
)
@mock_secretsmanager
def test_update_secret_with_tags_and_description():
conn = boto3.client("secretsmanager", region_name="us-west-2")