Add CreatedDate and LastChangedDate in secretsmanager responses (#4770)
This commit is contained in:
parent
54c7fd5e91
commit
3f534119f4
@ -61,6 +61,8 @@ class FakeSecret:
|
|||||||
kms_key_id=None,
|
kms_key_id=None,
|
||||||
version_id=None,
|
version_id=None,
|
||||||
version_stages=None,
|
version_stages=None,
|
||||||
|
last_changed_date=None,
|
||||||
|
created_date=None,
|
||||||
):
|
):
|
||||||
self.secret_id = secret_id
|
self.secret_id = secret_id
|
||||||
self.name = secret_id
|
self.name = secret_id
|
||||||
@ -72,14 +74,20 @@ class FakeSecret:
|
|||||||
self.kms_key_id = kms_key_id
|
self.kms_key_id = kms_key_id
|
||||||
self.version_id = version_id
|
self.version_id = version_id
|
||||||
self.version_stages = version_stages
|
self.version_stages = version_stages
|
||||||
|
self.last_changed_date = last_changed_date
|
||||||
|
self.created_date = created_date
|
||||||
self.rotation_enabled = False
|
self.rotation_enabled = False
|
||||||
self.rotation_lambda_arn = ""
|
self.rotation_lambda_arn = ""
|
||||||
self.auto_rotate_after_days = 0
|
self.auto_rotate_after_days = 0
|
||||||
self.deleted_date = None
|
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.description = description
|
||||||
self.tags = tags or []
|
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:
|
if kms_key_id is not None:
|
||||||
self.kms_key_id = kms_key_id
|
self.kms_key_id = kms_key_id
|
||||||
@ -134,12 +142,13 @@ class FakeSecret:
|
|||||||
"RotationLambdaARN": self.rotation_lambda_arn,
|
"RotationLambdaARN": self.rotation_lambda_arn,
|
||||||
"RotationRules": {"AutomaticallyAfterDays": self.auto_rotate_after_days},
|
"RotationRules": {"AutomaticallyAfterDays": self.auto_rotate_after_days},
|
||||||
"LastRotatedDate": None,
|
"LastRotatedDate": None,
|
||||||
"LastChangedDate": None,
|
"LastChangedDate": self.last_changed_date,
|
||||||
"LastAccessedDate": None,
|
"LastAccessedDate": None,
|
||||||
"DeletedDate": self.deleted_date,
|
"DeletedDate": self.deleted_date,
|
||||||
"Tags": self.tags,
|
"Tags": self.tags,
|
||||||
"VersionIdsToStages": version_id_to_stages,
|
"VersionIdsToStages": version_id_to_stages,
|
||||||
"SecretVersionsToStages": version_id_to_stages,
|
"SecretVersionsToStages": version_id_to_stages,
|
||||||
|
"CreatedDate": self.created_date,
|
||||||
}
|
}
|
||||||
|
|
||||||
def _form_version_ids_to_stages(self):
|
def _form_version_ids_to_stages(self):
|
||||||
@ -350,10 +359,11 @@ class SecretsManagerBackend(BaseBackend):
|
|||||||
if secret_binary is not None:
|
if secret_binary is not None:
|
||||||
secret_version["secret_binary"] = secret_binary
|
secret_version["secret_binary"] = secret_binary
|
||||||
|
|
||||||
|
update_time = int(time.time())
|
||||||
if secret_id in self.secrets:
|
if secret_id in self.secrets:
|
||||||
secret = self.secrets[secret_id]
|
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:
|
if "AWSPENDING" in version_stages:
|
||||||
secret.versions[version_id] = secret_version
|
secret.versions[version_id] = secret_version
|
||||||
@ -368,6 +378,8 @@ class SecretsManagerBackend(BaseBackend):
|
|||||||
description=description,
|
description=description,
|
||||||
tags=tags,
|
tags=tags,
|
||||||
kms_key_id=kms_key_id,
|
kms_key_id=kms_key_id,
|
||||||
|
last_changed_date=update_time,
|
||||||
|
created_date=update_time,
|
||||||
)
|
)
|
||||||
secret.set_versions({version_id: secret_version})
|
secret.set_versions({version_id: secret_version})
|
||||||
secret.set_default_version_id(version_id)
|
secret.set_default_version_id(version_id)
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
import boto3
|
import boto3
|
||||||
|
from dateutil.tz import tzlocal
|
||||||
|
|
||||||
from moto import mock_secretsmanager
|
from moto import mock_secretsmanager
|
||||||
from botocore.exceptions import ClientError
|
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]["Name"] == "test-secret-2"
|
||||||
assert secrets["SecretList"][1]["Tags"] == [{"Key": "a", "Value": "1"}]
|
assert secrets["SecretList"][1]["Tags"] == [{"Key": "a", "Value": "1"}]
|
||||||
assert secrets["SecretList"][1]["SecretVersionsToStages"] is not None
|
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
|
@mock_secretsmanager
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
import boto3
|
import boto3
|
||||||
|
from dateutil.tz import tzlocal
|
||||||
|
|
||||||
from moto import mock_secretsmanager, mock_lambda, settings
|
from moto import mock_secretsmanager, mock_lambda, settings
|
||||||
from moto.core import ACCOUNT_ID
|
from moto.core import ACCOUNT_ID
|
||||||
from botocore.exceptions import ClientError, ParamValidationError
|
from botocore.exceptions import ClientError, ParamValidationError
|
||||||
import string
|
import string
|
||||||
import pytz
|
import pytz
|
||||||
from datetime import datetime
|
from freezegun import freeze_time
|
||||||
|
from datetime import timedelta, datetime
|
||||||
import sure # noqa # pylint: disable=unused-import
|
import sure # noqa # pylint: disable=unused-import
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
import pytest
|
import pytest
|
||||||
@ -430,6 +434,14 @@ def test_describe_secret():
|
|||||||
assert secret_description["ARN"] != "" # Test arn not empty
|
assert secret_description["ARN"] != "" # Test arn not empty
|
||||||
assert secret_description_2["Name"] == ("test-secret-2")
|
assert secret_description_2["Name"] == ("test-secret-2")
|
||||||
assert secret_description_2["ARN"] != "" # Test arn not empty
|
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
|
@mock_secretsmanager
|
||||||
@ -967,6 +979,35 @@ def test_update_secret(pass_arn):
|
|||||||
assert created_secret["VersionId"] != updated_secret["VersionId"]
|
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
|
@mock_secretsmanager
|
||||||
def test_update_secret_with_tags_and_description():
|
def test_update_secret_with_tags_and_description():
|
||||||
conn = boto3.client("secretsmanager", region_name="us-west-2")
|
conn = boto3.client("secretsmanager", region_name="us-west-2")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user