diff --git a/moto/secretsmanager/models.py b/moto/secretsmanager/models.py index b2f185fb0bb0..d8e200f570e5 100644 --- a/moto/secretsmanager/models.py +++ b/moto/secretsmanager/models.py @@ -907,9 +907,12 @@ def list_secrets( filters: List[Dict[str, Any]], max_results: int = MAX_RESULTS_DEFAULT, next_token: Optional[str] = None, + include_planned_deletion: bool = False ) -> Tuple[List[Dict[str, Any]], Optional[str]]: secret_list: List[Dict[str, Any]] = [] for secret in self.secrets.values(): + if secret.deleted_date and not include_planned_deletion: + continue if _matches(secret, filters): secret_list.append(secret.to_dict()) diff --git a/moto/secretsmanager/responses.py b/moto/secretsmanager/responses.py index 72a7403fa1d4..26ce618cd674 100644 --- a/moto/secretsmanager/responses.py +++ b/moto/secretsmanager/responses.py @@ -175,8 +175,10 @@ def list_secrets(self) -> str: _validate_filters(filters) max_results = self._get_int_param("MaxResults") next_token = self._get_param("NextToken") + include_planned_deletion = self._get_param("IncludePlannedDeletion", if_none=False) secret_list, next_token = self.backend.list_secrets( - filters=filters, max_results=max_results, next_token=next_token + filters=filters, max_results=max_results, next_token=next_token, + include_planned_deletion=include_planned_deletion ) return json.dumps(dict(SecretList=secret_list, NextToken=next_token)) diff --git a/tests/test_secretsmanager/test_list_secrets.py b/tests/test_secretsmanager/test_list_secrets.py index 1acb8a9d3bdf..c18ac08f6d5d 100644 --- a/tests/test_secretsmanager/test_list_secrets.py +++ b/tests/test_secretsmanager/test_list_secrets.py @@ -285,3 +285,34 @@ def test_filter_with_owning_service(): resp = conn.list_secrets(Filters=[{"Key": "owning-service", "Values": ["n/a"]}]) assert resp["SecretList"] == [] + + +@mock_aws +def test_with_include_planned_deleted_secrets(): + conn = boto_client() + + conn.create_secret(Name="foo", SecretString="secret") + conn.create_secret(Name="bar", SecretString="secret") + + secrets = conn.list_secrets() + assert len(secrets['SecretList']) == 2 + + conn.delete_secret(SecretId="foo") + + # By default list secrets doesn't include deleted secrets + secrets = conn.list_secrets() + assert len(secrets['SecretList']) == 1 + assert secrets["SecretList"][0]["ARN"] is not None + assert secrets["SecretList"][0]["Name"] == "bar" + assert secrets["SecretList"][0]["SecretVersionsToStages"] is not None + + # list secrets when IncludePlannedDeletion param included + secrets = conn.list_secrets(IncludePlannedDeletion=True) + assert len(secrets['SecretList']) == 2 + + # list secret with filter and IncludePlannedDeletion params + secrets = conn.list_secrets(IncludePlannedDeletion=True, Filters=[{"Key": "name", "Values": ["foo"]}]) + assert len(secrets['SecretList']) == 1 + assert secrets["SecretList"][0]["ARN"] is not None + assert secrets["SecretList"][0]["Name"] == "foo" + assert secrets["SecretList"][0]["SecretVersionsToStages"] is not None