2022-01-25 10:24:26 +00:00
import os
2023-08-08 10:08:15 +00:00
import re
import string
2023-11-30 15:55:51 +00:00
from datetime import datetime , timedelta , timezone
2023-08-08 10:08:15 +00:00
from unittest import SkipTest
from uuid import uuid4
2022-01-25 10:24:26 +00:00
2018-06-08 05:31:44 +00:00
import boto3
2023-11-30 15:55:51 +00:00
import pytest
2023-08-08 10:08:15 +00:00
from botocore . exceptions import ClientError , ParamValidationError
2022-01-25 10:24:26 +00:00
from dateutil . tz import tzlocal
2023-08-08 10:08:15 +00:00
from freezegun import freeze_time
2018-06-08 05:31:44 +00:00
2024-01-07 12:03:33 +00:00
from moto import mock_aws , settings
2022-08-13 09:49:43 +00:00
from moto . core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID
2018-06-08 05:31:44 +00:00
2024-03-07 21:22:13 +00:00
from . import secretsmanager_aws_verified
2023-08-24 13:48:53 +00:00
DEFAULT_SECRET_NAME = " test-secret7 "
2019-05-22 09:45:22 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2018-06-08 05:31:44 +00:00
def test_get_secret_value ( ) :
2018-06-10 05:08:10 +00:00
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
2018-06-08 05:31:44 +00:00
2021-10-18 19:44:29 +00:00
conn . create_secret ( Name = " java-util-test-password " , SecretString = " foosecret " )
2018-06-08 05:31:44 +00:00
result = conn . get_secret_value ( SecretId = " java-util-test-password " )
2018-07-14 07:39:19 +00:00
assert result [ " SecretString " ] == " foosecret "
2019-08-23 09:57:15 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2022-06-08 19:54:51 +00:00
def test_secret_arn ( ) :
region = " us-west-2 "
conn = boto3 . client ( " secretsmanager " , region_name = region )
create_dict = conn . create_secret (
Name = DEFAULT_SECRET_NAME ,
SecretString = " secret_string " ,
)
assert re . match (
f " arn:aws:secretsmanager: { region } : { ACCOUNT_ID } :secret: { DEFAULT_SECRET_NAME } - "
+ r " \ w {6} " ,
create_dict [ " ARN " ] ,
)
2024-01-07 12:03:33 +00:00
@mock_aws
2022-02-11 12:49:14 +00:00
def test_create_secret_with_client_request_token ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
version_id = " eb41453f-25bb-4025-b7f4-850cfca0ce71 "
create_dict = conn . create_secret (
Name = DEFAULT_SECRET_NAME ,
SecretString = " secret_string " ,
ClientRequestToken = version_id ,
)
assert create_dict
assert create_dict [ " VersionId " ] == version_id
2024-01-07 12:03:33 +00:00
@mock_aws
2019-11-23 06:29:30 +00:00
def test_get_secret_value_by_arn ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
2021-06-23 17:03:11 +00:00
name = " java-util-test-password "
2019-11-23 06:29:30 +00:00
secret_value = " test_get_secret_value_by_arn "
2021-06-23 17:03:11 +00:00
result = conn . create_secret ( Name = name , SecretString = secret_value )
arn = result [ " ARN " ]
2023-08-08 10:08:15 +00:00
assert re . match (
f " ^arn:aws:secretsmanager:us-west-2: { ACCOUNT_ID } :secret: { name } " , arn
)
2021-06-23 17:03:11 +00:00
result = conn . get_secret_value ( SecretId = arn )
2019-11-23 06:29:30 +00:00
assert result [ " SecretString " ] == secret_value
2024-01-07 12:03:33 +00:00
@mock_aws
2019-05-28 15:32:43 +00:00
def test_get_secret_value_binary ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
2021-10-18 19:44:29 +00:00
conn . create_secret ( Name = " java-util-test-password " , SecretBinary = b " foosecret " )
2019-05-28 15:32:43 +00:00
result = conn . get_secret_value ( SecretId = " java-util-test-password " )
2021-07-26 06:40:39 +00:00
assert result [ " SecretBinary " ] == b " foosecret "
2019-05-28 15:32:43 +00:00
2019-08-23 09:57:15 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2018-07-14 07:39:19 +00:00
def test_get_secret_that_does_not_exist ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
2020-10-06 05:54:49 +00:00
with pytest . raises ( ClientError ) as cm :
2021-10-18 19:44:29 +00:00
conn . get_secret_value ( SecretId = " i-dont-exist " )
2018-07-14 07:39:19 +00:00
2020-10-06 06:46:05 +00:00
assert (
" Secrets Manager can ' t find the specified secret. "
== cm . value . response [ " Error " ] [ " Message " ]
)
2019-10-16 04:16:38 +00:00
2019-08-23 09:57:15 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2018-08-15 17:33:38 +00:00
def test_get_secret_that_does_not_match ( ) :
2018-08-10 23:40:31 +00:00
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
2021-10-18 19:44:29 +00:00
conn . create_secret ( Name = " java-util-test-password " , SecretString = " foosecret " )
2018-08-10 23:40:31 +00:00
2020-10-06 05:54:49 +00:00
with pytest . raises ( ClientError ) as cm :
2021-10-18 19:44:29 +00:00
conn . get_secret_value ( SecretId = " i-dont-match " )
2018-07-14 07:39:19 +00:00
2020-10-06 06:46:05 +00:00
assert (
" Secrets Manager can ' t find the specified secret. "
== cm . value . response [ " Error " ] [ " Message " ]
)
2019-04-18 11:58:50 +00:00
2019-10-17 23:13:22 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2019-04-18 11:58:50 +00:00
def test_get_secret_value_that_is_marked_deleted ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
conn . create_secret ( Name = " test-secret " , SecretString = " foosecret " )
2019-04-18 15:47:15 +00:00
conn . delete_secret ( SecretId = " test-secret " )
2019-04-18 11:58:50 +00:00
2020-10-06 05:54:49 +00:00
with pytest . raises ( ClientError ) :
2021-10-18 19:44:29 +00:00
conn . get_secret_value ( SecretId = " test-secret " )
2019-04-18 11:58:50 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2019-10-15 10:57:16 +00:00
def test_get_secret_that_has_no_value ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
2023-08-24 13:48:53 +00:00
conn . create_secret ( Name = " secret-no-value " )
2019-10-15 10:57:16 +00:00
2020-10-06 05:54:49 +00:00
with pytest . raises ( ClientError ) as cm :
2023-08-24 13:48:53 +00:00
conn . get_secret_value ( SecretId = " secret-no-value " )
2019-10-15 10:57:16 +00:00
2020-10-06 06:46:05 +00:00
assert (
" Secrets Manager can ' t find the specified secret value for staging label: AWSCURRENT "
== cm . value . response [ " Error " ] [ " Message " ]
)
2019-10-16 04:16:38 +00:00
2019-10-15 10:57:16 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2020-10-05 11:22:54 +00:00
def test_get_secret_version_that_does_not_exist ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
2023-08-24 13:48:53 +00:00
result = conn . create_secret ( Name = " java-util-test-password " , SecretString = " v " )
2020-10-05 11:22:54 +00:00
secret_arn = result [ " ARN " ]
missing_version_id = " 00000000-0000-0000-0000-000000000000 "
2020-10-06 06:04:09 +00:00
with pytest . raises ( ClientError ) as cm :
2020-10-05 11:22:54 +00:00
conn . get_secret_value ( SecretId = secret_arn , VersionId = missing_version_id )
2020-10-06 06:46:05 +00:00
assert (
2023-08-24 13:48:53 +00:00
" Secrets Manager can ' t find the specified "
2023-08-08 10:08:15 +00:00
" secret value for VersionId: 00000000-0000-0000-0000-000000000000 "
2020-10-06 06:46:05 +00:00
) == cm . value . response [ " Error " ] [ " Message " ]
2020-10-05 11:22:54 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2022-06-18 11:20:14 +00:00
def test_get_secret_version_stage_mismatch ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
result = conn . create_secret ( Name = " test-secret " , SecretString = " secret " )
secret_arn = result [ " ARN " ]
rotated_secret = conn . rotate_secret (
SecretId = secret_arn , RotationRules = { " AutomaticallyAfterDays " : 42 }
)
desc_secret = conn . describe_secret ( SecretId = secret_arn )
versions_to_stages = desc_secret [ " VersionIdsToStages " ]
version_for_test = rotated_secret [ " VersionId " ]
stages_for_version = versions_to_stages [ version_for_test ]
assert " AWSPENDING " not in stages_for_version
with pytest . raises ( ClientError ) as cm :
conn . get_secret_value (
SecretId = secret_arn , VersionId = version_for_test , VersionStage = " AWSPENDING "
)
assert (
" You provided a VersionStage that is not associated to the provided VersionId. "
) == cm . value . response [ " Error " ] [ " Message " ]
2024-01-07 12:03:33 +00:00
@mock_aws
2018-07-14 07:39:19 +00:00
def test_create_secret ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-east-1 " )
result = conn . create_secret ( Name = " test-secret " , SecretString = " foosecret " )
2018-10-24 21:06:23 +00:00
assert result [ " ARN " ]
2018-07-14 07:39:19 +00:00
assert result [ " Name " ] == " test-secret "
secret = conn . get_secret_value ( SecretId = " test-secret " )
assert secret [ " SecretString " ] == " foosecret "
2018-07-16 19:39:59 +00:00
2019-08-23 09:57:15 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2018-12-21 22:04:52 +00:00
def test_create_secret_with_tags ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-east-1 " )
secret_name = " test-secret-with-tags "
result = conn . create_secret (
Name = secret_name ,
SecretString = " foosecret " ,
Tags = [ { " Key " : " Foo " , " Value " : " Bar " } , { " Key " : " Mykey " , " Value " : " Myvalue " } ] ,
)
assert result [ " ARN " ]
assert result [ " Name " ] == secret_name
secret_value = conn . get_secret_value ( SecretId = secret_name )
assert secret_value [ " SecretString " ] == " foosecret "
secret_details = conn . describe_secret ( SecretId = secret_name )
assert secret_details [ " Tags " ] == [
{ " Key " : " Foo " , " Value " : " Bar " } ,
{ " Key " : " Mykey " , " Value " : " Myvalue " } ,
]
2019-04-05 14:00:11 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2020-04-24 19:47:11 +00:00
def test_create_secret_with_description ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-east-1 " )
secret_name = " test-secret-with-tags "
result = conn . create_secret (
Name = secret_name , SecretString = " foosecret " , Description = " desc "
)
assert result [ " ARN " ]
assert result [ " Name " ] == secret_name
secret_value = conn . get_secret_value ( SecretId = secret_name )
assert secret_value [ " SecretString " ] == " foosecret "
secret_details = conn . describe_secret ( SecretId = secret_name )
assert secret_details [ " Description " ] == " desc "
2024-01-07 12:03:33 +00:00
@mock_aws
2020-04-24 19:47:11 +00:00
def test_create_secret_with_tags_and_description ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-east-1 " )
secret_name = " test-secret-with-tags "
result = conn . create_secret (
Name = secret_name ,
SecretString = " foosecret " ,
Description = " desc " ,
Tags = [ { " Key " : " Foo " , " Value " : " Bar " } , { " Key " : " Mykey " , " Value " : " Myvalue " } ] ,
)
assert result [ " ARN " ]
assert result [ " Name " ] == secret_name
secret_value = conn . get_secret_value ( SecretId = secret_name )
assert secret_value [ " SecretString " ] == " foosecret "
secret_details = conn . describe_secret ( SecretId = secret_name )
assert secret_details [ " Tags " ] == [
{ " Key " : " Foo " , " Value " : " Bar " } ,
{ " Key " : " Mykey " , " Value " : " Myvalue " } ,
]
assert secret_details [ " Description " ] == " desc "
2024-01-07 12:03:33 +00:00
@mock_aws
2023-08-24 13:48:53 +00:00
def test_create_secret_without_value ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-east-2 " )
secret_name = f " secret- { str ( uuid4 ( ) ) [ 0 : 6 ] } "
create = conn . create_secret ( Name = secret_name )
assert set ( create . keys ( ) ) == { " ARN " , " Name " , " ResponseMetadata " }
describe = conn . describe_secret ( SecretId = secret_name )
assert set ( describe . keys ( ) ) == {
" ARN " ,
" Name " ,
" LastChangedDate " ,
" CreatedDate " ,
" ResponseMetadata " ,
}
with pytest . raises ( ClientError ) as exc :
conn . get_secret_value ( SecretId = secret_name )
err = exc . value . response [ " Error " ]
assert err [ " Code " ] == " ResourceNotFoundException "
updated = conn . update_secret (
SecretId = secret_name ,
Description = " new desc " ,
)
assert set ( updated . keys ( ) ) == { " ARN " , " Name " , " ResponseMetadata " }
describe = conn . describe_secret ( SecretId = secret_name )
assert set ( describe . keys ( ) ) == {
" ARN " ,
" Name " ,
" Description " ,
" LastChangedDate " ,
" CreatedDate " ,
" ResponseMetadata " ,
}
deleted = conn . delete_secret ( SecretId = secret_name )
assert set ( deleted . keys ( ) ) == { " ARN " , " Name " , " DeletionDate " , " ResponseMetadata " }
2024-01-07 12:03:33 +00:00
@mock_aws
2023-09-05 21:04:44 +00:00
def test_create_secret_that_has_no_value_and_then_update ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
conn . create_secret ( Name = " secret-no-value " )
conn . update_secret (
SecretId = " secret-no-value " ,
SecretString = " barsecret " ,
Description = " desc " ,
)
secret = conn . get_secret_value ( SecretId = " secret-no-value " )
assert secret [ " SecretString " ] == " barsecret "
2024-01-07 12:03:33 +00:00
@mock_aws
2023-08-24 13:48:53 +00:00
def test_update_secret_without_value ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-east-2 " )
secret_name = f " secret- { str ( uuid4 ( ) ) [ 0 : 6 ] } "
create = conn . create_secret ( Name = secret_name , SecretString = " foosecret " )
assert set ( create . keys ( ) ) == { " ARN " , " Name " , " VersionId " , " ResponseMetadata " }
version_id = create [ " VersionId " ]
describe1 = conn . describe_secret ( SecretId = secret_name )
assert set ( describe1 . keys ( ) ) == {
" ARN " ,
" Name " ,
" LastChangedDate " ,
" VersionIdsToStages " ,
" CreatedDate " ,
" ResponseMetadata " ,
}
conn . get_secret_value ( SecretId = secret_name )
updated = conn . update_secret ( SecretId = secret_name , Description = " desc " )
assert set ( updated . keys ( ) ) == { " ARN " , " Name " , " ResponseMetadata " }
describe2 = conn . describe_secret ( SecretId = secret_name )
# AWS also includes 'LastAccessedDate'
assert set ( describe2 . keys ( ) ) == {
" ARN " ,
" Name " ,
" Description " ,
" LastChangedDate " ,
" VersionIdsToStages " ,
" CreatedDate " ,
" ResponseMetadata " ,
}
assert describe1 [ " VersionIdsToStages " ] == describe2 [ " VersionIdsToStages " ]
value = conn . get_secret_value ( SecretId = secret_name )
assert value [ " SecretString " ] == " foosecret "
assert value [ " VersionId " ] == version_id
conn . delete_secret ( SecretId = secret_name )
2024-01-07 12:03:33 +00:00
@mock_aws
2019-04-05 14:00:11 +00:00
def test_delete_secret ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
conn . create_secret ( Name = " test-secret " , SecretString = " foosecret " )
2019-04-18 11:58:50 +00:00
deleted_secret = conn . delete_secret ( SecretId = " test-secret " )
2019-04-05 14:00:11 +00:00
2019-04-18 11:58:50 +00:00
assert deleted_secret [ " ARN " ]
assert deleted_secret [ " Name " ] == " test-secret "
2022-12-09 23:56:08 +00:00
assert deleted_secret [ " DeletionDate " ] > datetime . fromtimestamp ( 1 , timezone . utc )
2019-04-18 11:58:50 +00:00
secret_details = conn . describe_secret ( SecretId = " test-secret " )
assert secret_details [ " ARN " ]
assert secret_details [ " Name " ] == " test-secret "
2022-12-09 23:56:08 +00:00
assert secret_details [ " DeletedDate " ] > datetime . fromtimestamp ( 1 , timezone . utc )
2019-04-18 11:58:50 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2022-03-08 10:17:28 +00:00
def test_delete_secret_by_arn ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
secret = conn . create_secret ( Name = " test-secret " , SecretString = " foosecret " )
deleted_secret = conn . delete_secret ( SecretId = secret [ " ARN " ] )
assert deleted_secret [ " ARN " ] == secret [ " ARN " ]
assert deleted_secret [ " Name " ] == " test-secret "
2022-12-09 23:56:08 +00:00
assert deleted_secret [ " DeletionDate " ] > datetime . fromtimestamp ( 1 , timezone . utc )
2022-03-08 10:17:28 +00:00
secret_details = conn . describe_secret ( SecretId = " test-secret " )
assert secret_details [ " ARN " ] == secret [ " ARN " ]
assert secret_details [ " Name " ] == " test-secret "
2022-12-09 23:56:08 +00:00
assert secret_details [ " DeletedDate " ] > datetime . fromtimestamp ( 1 , timezone . utc )
2022-03-08 10:17:28 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2019-04-18 11:58:50 +00:00
def test_delete_secret_force ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
conn . create_secret ( Name = " test-secret " , SecretString = " foosecret " )
2019-04-05 14:00:11 +00:00
2019-04-18 11:58:50 +00:00
result = conn . delete_secret ( SecretId = " test-secret " , ForceDeleteWithoutRecovery = True )
2019-04-05 14:00:11 +00:00
2019-04-18 11:58:50 +00:00
assert result [ " ARN " ]
2022-12-09 23:56:08 +00:00
assert result [ " DeletionDate " ] > datetime . fromtimestamp ( 1 , timezone . utc )
2019-04-05 14:00:11 +00:00
assert result [ " Name " ] == " test-secret "
2020-10-06 05:54:49 +00:00
with pytest . raises ( ClientError ) :
2023-08-24 13:48:53 +00:00
conn . get_secret_value ( SecretId = " test-secret " )
2019-04-05 14:00:11 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2022-02-11 12:49:14 +00:00
def test_delete_secret_force_no_such_secret ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
deleted_secret = conn . delete_secret (
SecretId = DEFAULT_SECRET_NAME , ForceDeleteWithoutRecovery = True
)
assert deleted_secret
assert deleted_secret [ " Name " ] == DEFAULT_SECRET_NAME
2024-01-07 12:03:33 +00:00
@mock_aws
2020-06-10 07:54:03 +00:00
def test_delete_secret_force_with_arn ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
create_secret = conn . create_secret ( Name = " test-secret " , SecretString = " foosecret " )
result = conn . delete_secret (
SecretId = create_secret [ " ARN " ] , ForceDeleteWithoutRecovery = True
)
assert result [ " ARN " ]
2022-12-09 23:56:08 +00:00
assert result [ " DeletionDate " ] > datetime . fromtimestamp ( 1 , timezone . utc )
2020-06-10 07:54:03 +00:00
assert result [ " Name " ] == " test-secret "
2020-10-06 05:54:49 +00:00
with pytest . raises ( ClientError ) :
2023-08-24 13:48:53 +00:00
conn . get_secret_value ( SecretId = " test-secret " )
2020-06-10 07:54:03 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2019-04-05 14:00:11 +00:00
def test_delete_secret_that_does_not_exist ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
2020-10-06 05:54:49 +00:00
with pytest . raises ( ClientError ) :
2022-02-11 12:49:14 +00:00
conn . delete_secret ( SecretId = " i-dont-exist " )
2019-04-05 14:00:11 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2019-04-18 11:58:50 +00:00
def test_delete_secret_fails_with_both_force_delete_flag_and_recovery_window_flag ( ) :
2019-04-05 14:00:11 +00:00
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
conn . create_secret ( Name = " test-secret " , SecretString = " foosecret " )
2020-10-06 05:54:49 +00:00
with pytest . raises ( ClientError ) :
2021-10-18 19:44:29 +00:00
conn . delete_secret (
2019-04-18 11:58:50 +00:00
SecretId = " test-secret " ,
RecoveryWindowInDays = 1 ,
ForceDeleteWithoutRecovery = True ,
)
2019-04-05 14:00:11 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2023-07-01 11:35:22 +00:00
def test_delete_secret_recovery_window_invalid_values ( ) :
2019-04-05 14:00:11 +00:00
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
conn . create_secret ( Name = " test-secret " , SecretString = " foosecret " )
2023-07-01 11:35:22 +00:00
for nr in [ 0 , 2 , 6 , 31 , 100 ] :
with pytest . raises ( ClientError ) as exc :
conn . delete_secret ( SecretId = " test-secret " , RecoveryWindowInDays = nr )
err = exc . value . response [ " Error " ]
assert err [ " Code " ] == " InvalidParameterException "
assert (
" RecoveryWindowInDays value must be between 7 and 30 days (inclusive) "
in err [ " Message " ]
)
2019-04-18 11:58:50 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2022-02-11 12:49:14 +00:00
def test_delete_secret_force_no_such_secret_with_invalid_recovery_window ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
2023-07-01 11:35:22 +00:00
for nr in [ 0 , 2 , 6 , 31 , 100 ] :
with pytest . raises ( ClientError ) as exc :
conn . delete_secret (
SecretId = " test-secret " ,
RecoveryWindowInDays = nr ,
ForceDeleteWithoutRecovery = True ,
)
err = exc . value . response [ " Error " ]
assert err [ " Code " ] == " InvalidParameterException "
assert (
" RecoveryWindowInDays value must be between 7 and 30 days (inclusive) "
in err [ " Message " ]
2022-02-11 12:49:14 +00:00
)
2024-01-07 12:03:33 +00:00
@mock_aws
2019-04-18 11:58:50 +00:00
def test_delete_secret_that_is_marked_deleted ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
conn . create_secret ( Name = " test-secret " , SecretString = " foosecret " )
2021-10-18 19:44:29 +00:00
conn . delete_secret ( SecretId = " test-secret " )
2019-04-18 11:58:50 +00:00
2020-10-06 05:54:49 +00:00
with pytest . raises ( ClientError ) :
2021-10-18 19:44:29 +00:00
conn . delete_secret ( SecretId = " test-secret " )
2019-04-05 14:00:11 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2018-07-16 19:39:59 +00:00
def test_get_random_password_default_length ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
random_password = conn . get_random_password ( )
assert len ( random_password [ " RandomPassword " ] ) == 32
2019-10-31 15:44:26 +00:00
2018-07-16 19:39:59 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2018-07-16 19:39:59 +00:00
def test_get_random_password_default_requirements ( ) :
# When require_each_included_type, default true
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
random_password = conn . get_random_password ( )
# Should contain lowercase, upppercase, digit, special character
assert any ( c . islower ( ) for c in random_password [ " RandomPassword " ] )
assert any ( c . isupper ( ) for c in random_password [ " RandomPassword " ] )
assert any ( c . isdigit ( ) for c in random_password [ " RandomPassword " ] )
assert any ( c in string . punctuation for c in random_password [ " RandomPassword " ] )
2019-10-31 15:44:26 +00:00
2018-07-16 19:39:59 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2018-07-16 19:39:59 +00:00
def test_get_random_password_custom_length ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
random_password = conn . get_random_password ( PasswordLength = 50 )
assert len ( random_password [ " RandomPassword " ] ) == 50
2019-10-31 15:44:26 +00:00
2018-07-16 19:39:59 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2018-07-16 19:39:59 +00:00
def test_get_random_exclude_lowercase ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
random_password = conn . get_random_password ( PasswordLength = 55 , ExcludeLowercase = True )
2020-10-06 05:54:49 +00:00
assert not any ( c . islower ( ) for c in random_password [ " RandomPassword " ] )
2018-07-16 19:39:59 +00:00
2019-08-23 09:57:15 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2018-07-16 19:39:59 +00:00
def test_get_random_exclude_uppercase ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
random_password = conn . get_random_password ( PasswordLength = 55 , ExcludeUppercase = True )
2020-10-06 05:54:49 +00:00
assert not any ( c . isupper ( ) for c in random_password [ " RandomPassword " ] )
2018-07-16 19:39:59 +00:00
2019-08-23 09:57:15 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2018-07-16 19:39:59 +00:00
def test_get_random_exclude_characters_and_symbols ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
random_password = conn . get_random_password (
PasswordLength = 20 , ExcludeCharacters = " xyzDje@?!. "
)
2020-10-06 05:54:49 +00:00
assert not any ( c in " xyzDje@?!. " for c in random_password [ " RandomPassword " ] )
2020-08-03 12:42:42 +00:00
assert len ( random_password [ " RandomPassword " ] ) == 20
2018-07-16 19:39:59 +00:00
2019-08-23 09:57:15 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2018-07-16 19:39:59 +00:00
def test_get_random_exclude_numbers ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
random_password = conn . get_random_password ( PasswordLength = 100 , ExcludeNumbers = True )
2020-10-06 05:54:49 +00:00
assert not any ( c . isdigit ( ) for c in random_password [ " RandomPassword " ] )
2018-07-16 19:39:59 +00:00
2019-08-23 09:57:15 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2018-07-16 19:39:59 +00:00
def test_get_random_exclude_punctuation ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
random_password = conn . get_random_password (
PasswordLength = 100 , ExcludePunctuation = True
)
2020-10-06 05:54:49 +00:00
assert not any ( c in string . punctuation for c in random_password [ " RandomPassword " ] )
2018-07-16 19:39:59 +00:00
2019-08-23 09:57:15 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2018-07-16 19:39:59 +00:00
def test_get_random_include_space_false ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
random_password = conn . get_random_password ( PasswordLength = 300 )
2020-10-06 05:54:49 +00:00
assert not any ( c . isspace ( ) for c in random_password [ " RandomPassword " ] )
2018-07-16 19:39:59 +00:00
2019-08-23 09:57:15 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2018-07-16 19:39:59 +00:00
def test_get_random_include_space_true ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
random_password = conn . get_random_password ( PasswordLength = 4 , IncludeSpace = True )
2020-10-06 05:54:49 +00:00
assert any ( c . isspace ( ) for c in random_password [ " RandomPassword " ] )
2018-07-16 19:39:59 +00:00
2019-08-23 09:57:15 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2018-07-16 19:39:59 +00:00
def test_get_random_require_each_included_type ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
random_password = conn . get_random_password (
PasswordLength = 4 , RequireEachIncludedType = True
)
2020-10-06 05:54:49 +00:00
assert any ( c in string . punctuation for c in random_password [ " RandomPassword " ] )
assert any ( c in string . ascii_lowercase for c in random_password [ " RandomPassword " ] )
assert any ( c in string . ascii_uppercase for c in random_password [ " RandomPassword " ] )
assert any ( c in string . digits for c in random_password [ " RandomPassword " ] )
2018-07-16 19:39:59 +00:00
2019-08-23 09:57:15 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2018-07-16 19:39:59 +00:00
def test_get_random_too_short_password ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
2020-10-06 05:54:49 +00:00
with pytest . raises ( ClientError ) :
2021-10-18 19:44:29 +00:00
conn . get_random_password ( PasswordLength = 3 )
2018-07-16 19:39:59 +00:00
2019-08-23 09:57:15 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2018-07-16 19:39:59 +00:00
def test_get_random_too_long_password ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
2020-10-06 05:54:49 +00:00
with pytest . raises ( Exception ) :
2021-10-18 19:44:29 +00:00
conn . get_random_password ( PasswordLength = 5555 )
2018-08-06 21:40:33 +00:00
2019-08-23 09:57:15 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2018-08-06 21:40:33 +00:00
def test_describe_secret ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
conn . create_secret ( Name = " test-secret " , SecretString = " foosecret " )
2019-10-31 15:44:26 +00:00
2018-10-24 21:06:23 +00:00
conn . create_secret ( Name = " test-secret-2 " , SecretString = " barsecret " )
2019-10-31 15:44:26 +00:00
2018-08-06 21:40:33 +00:00
secret_description = conn . describe_secret ( SecretId = " test-secret " )
2018-10-24 21:06:23 +00:00
secret_description_2 = conn . describe_secret ( SecretId = " test-secret-2 " )
2018-08-06 21:40:33 +00:00
assert secret_description # Returned dict is not empty
2018-10-24 21:06:23 +00:00
assert secret_description [ " Name " ] == ( " test-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
2022-01-25 10:24:26 +00:00
assert secret_description [ " CreatedDate " ] < = datetime . now ( tz = tzlocal ( ) )
2022-12-09 23:56:08 +00:00
assert secret_description [ " CreatedDate " ] > datetime . fromtimestamp ( 1 , timezone . utc )
2022-01-25 10:24:26 +00:00
assert secret_description_2 [ " CreatedDate " ] < = datetime . now ( tz = tzlocal ( ) )
2022-12-09 23:56:08 +00:00
assert secret_description_2 [ " CreatedDate " ] > datetime . fromtimestamp ( 1 , timezone . utc )
2022-01-25 10:24:26 +00:00
assert secret_description [ " LastChangedDate " ] < = datetime . now ( tz = tzlocal ( ) )
2022-12-09 23:56:08 +00:00
assert secret_description [ " LastChangedDate " ] > datetime . fromtimestamp (
1 , timezone . utc
)
2022-01-25 10:24:26 +00:00
assert secret_description_2 [ " LastChangedDate " ] < = datetime . now ( tz = tzlocal ( ) )
2022-12-09 23:56:08 +00:00
assert secret_description_2 [ " LastChangedDate " ] > datetime . fromtimestamp (
1 , timezone . utc
)
2018-08-06 21:40:33 +00:00
2019-08-23 09:57:15 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2023-03-25 12:00:17 +00:00
@pytest.mark.parametrize ( " name " , [ " testsecret " , " test-secret " ] )
def test_describe_secret_with_arn ( name ) :
2019-11-23 07:18:06 +00:00
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
2023-03-25 12:00:17 +00:00
results = conn . create_secret ( Name = name , SecretString = " foosecret " )
2019-11-23 07:18:06 +00:00
2019-11-23 10:02:00 +00:00
secret_description = conn . describe_secret ( SecretId = results [ " ARN " ] )
2019-11-23 07:18:06 +00:00
assert secret_description # Returned dict is not empty
2023-08-08 10:08:15 +00:00
assert secret_description [ " Name " ] == name
assert secret_description [ " ARN " ] == results [ " ARN " ]
assert conn . list_secrets ( ) [ " SecretList " ] [ 0 ] [ " ARN " ] == results [ " ARN " ]
2019-11-23 07:18:06 +00:00
2023-03-25 12:00:17 +00:00
# We can also supply a partial ARN
partial_arn = f " arn:aws:secretsmanager:us-west-2: { ACCOUNT_ID } :secret: { name } "
resp = conn . get_secret_value ( SecretId = partial_arn )
assert resp [ " Name " ] == name
resp = conn . describe_secret ( SecretId = partial_arn )
assert resp [ " Name " ] == name
2019-11-23 07:18:06 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2021-08-03 14:46:23 +00:00
def test_describe_secret_with_KmsKeyId ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
results = conn . create_secret (
Name = " test-secret " , SecretString = " foosecret " , KmsKeyId = " dummy_arn "
)
secret_description = conn . describe_secret ( SecretId = results [ " ARN " ] )
2023-08-08 10:08:15 +00:00
assert secret_description [ " KmsKeyId " ] == " dummy_arn "
assert (
conn . list_secrets ( ) [ " SecretList " ] [ 0 ] [ " KmsKeyId " ]
2021-08-03 14:46:23 +00:00
== ( secret_description [ " KmsKeyId " ] )
)
2024-01-07 12:03:33 +00:00
@mock_aws
2018-08-06 21:40:33 +00:00
def test_describe_secret_that_does_not_exist ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
2020-10-06 05:54:49 +00:00
with pytest . raises ( ClientError ) :
2021-10-18 19:44:29 +00:00
conn . get_secret_value ( SecretId = " i-dont-exist " )
2018-08-13 19:49:35 +00:00
2019-08-23 09:57:15 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2018-08-13 19:49:35 +00:00
def test_describe_secret_that_does_not_match ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
conn . create_secret ( Name = " test-secret " , SecretString = " foosecret " )
2019-10-31 15:44:26 +00:00
2020-10-06 05:54:49 +00:00
with pytest . raises ( ClientError ) :
2021-10-18 19:44:29 +00:00
conn . get_secret_value ( SecretId = " i-dont-match " )
2018-08-15 17:52:30 +00:00
2019-04-05 12:33:28 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2019-04-21 17:11:20 +00:00
def test_restore_secret ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
conn . create_secret ( Name = " test-secret " , SecretString = " foosecret " )
conn . delete_secret ( SecretId = " test-secret " )
described_secret_before = conn . describe_secret ( SecretId = " test-secret " )
2022-12-09 23:56:08 +00:00
assert described_secret_before [ " DeletedDate " ] > datetime . fromtimestamp (
1 , timezone . utc
)
2019-04-21 17:11:20 +00:00
restored_secret = conn . restore_secret ( SecretId = " test-secret " )
assert restored_secret [ " ARN " ]
assert restored_secret [ " Name " ] == " test-secret "
described_secret_after = conn . describe_secret ( SecretId = " test-secret " )
assert " DeletedDate " not in described_secret_after
2024-01-07 12:03:33 +00:00
@mock_aws
2019-04-21 17:11:20 +00:00
def test_restore_secret_that_is_not_deleted ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
conn . create_secret ( Name = " test-secret " , SecretString = " foosecret " )
restored_secret = conn . restore_secret ( SecretId = " test-secret " )
assert restored_secret [ " ARN " ]
assert restored_secret [ " Name " ] == " test-secret "
2024-01-07 12:03:33 +00:00
@mock_aws
2019-04-21 17:11:20 +00:00
def test_restore_secret_that_does_not_exist ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
2020-10-06 05:54:49 +00:00
with pytest . raises ( ClientError ) :
2021-10-18 19:44:29 +00:00
conn . restore_secret ( SecretId = " i-dont-exist " )
2019-04-21 17:11:20 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2023-01-03 19:22:38 +00:00
def test_cancel_rotate_secret_with_invalid_secret_id ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-east-1 " )
with pytest . raises ( ClientError ) :
conn . cancel_rotate_secret ( SecretId = " invalid_id " )
2024-01-07 12:03:33 +00:00
@mock_aws
2023-01-03 19:22:38 +00:00
def test_cancel_rotate_secret_after_delete ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-east-1 " )
conn . create_secret (
Name = DEFAULT_SECRET_NAME , SecretString = " foosecret " , Description = " foodescription "
)
conn . delete_secret (
SecretId = DEFAULT_SECRET_NAME ,
RecoveryWindowInDays = 7 ,
ForceDeleteWithoutRecovery = False ,
)
with pytest . raises ( ClientError ) :
conn . cancel_rotate_secret ( SecretId = DEFAULT_SECRET_NAME )
2024-01-07 12:03:33 +00:00
@mock_aws
2023-01-03 19:22:38 +00:00
def test_cancel_rotate_secret_before_enable ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-east-1 " )
conn . create_secret (
Name = DEFAULT_SECRET_NAME , SecretString = " foosecret " , Description = " foodescription "
)
with pytest . raises ( ClientError ) :
conn . cancel_rotate_secret ( SecretId = DEFAULT_SECRET_NAME )
2024-01-07 12:03:33 +00:00
@mock_aws
2023-01-03 19:22:38 +00:00
def test_cancel_rotate_secret ( ) :
if not settings . TEST_SERVER_MODE :
raise SkipTest ( " rotation requires a server to be running " )
from tests . test_awslambda . utilities import get_role_name
lambda_conn = boto3 . client (
" lambda " , region_name = " us-east-1 " , endpoint_url = " http://localhost:5000 "
)
func = lambda_conn . create_function (
FunctionName = " testFunction " ,
2023-08-31 06:47:49 +00:00
Runtime = " python3.11 " ,
2023-01-03 19:22:38 +00:00
Role = get_role_name ( ) ,
Handler = " lambda_function.lambda_handler " ,
Code = { " ZipFile " : get_rotation_zip_file ( ) } ,
Description = " Secret rotator " ,
Timeout = 3 ,
MemorySize = 128 ,
Publish = True ,
)
secrets_conn = boto3 . client ( " secretsmanager " , region_name = " us-east-1 " )
secrets_conn . create_secret (
Name = DEFAULT_SECRET_NAME , SecretString = " foosecret " , Description = " foodescription "
)
secrets_conn . rotate_secret (
SecretId = DEFAULT_SECRET_NAME ,
RotationLambdaARN = func [ " FunctionArn " ] ,
2023-08-08 10:08:15 +00:00
RotationRules = { " AutomaticallyAfterDays " : 30 } ,
2023-01-03 19:22:38 +00:00
)
secrets_conn . cancel_rotate_secret ( SecretId = DEFAULT_SECRET_NAME )
cancelled_rotation = secrets_conn . describe_secret ( SecretId = DEFAULT_SECRET_NAME )
assert not cancelled_rotation [ " RotationEnabled " ]
# The function config should be preserved
assert cancelled_rotation [ " RotationLambdaARN " ]
2024-01-07 12:03:33 +00:00
@mock_aws
2018-08-15 18:04:44 +00:00
def test_rotate_secret ( ) :
2023-05-12 10:10:52 +00:00
# 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 " ,
)
2020-10-05 10:10:32 +00:00
2023-05-12 10:10:52 +00:00
# Execute
rotated_secret = conn . rotate_secret (
SecretId = DEFAULT_SECRET_NAME ,
RotationRules = { " AutomaticallyAfterDays " : rotate_after_days } ,
)
describe_secret = conn . describe_secret ( SecretId = DEFAULT_SECRET_NAME )
# 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
# can't do freeze time tests in servermode tests
if settings . TEST_SERVER_MODE :
return
assert describe_secret [ " LastChangedDate " ] == frozen_time
assert describe_secret [ " NextRotationDate " ] == frozen_time + timedelta (
days = rotate_after_days
)
2020-10-05 10:10:32 +00:00
2018-08-15 18:04:44 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2022-11-18 21:18:47 +00:00
def test_rotate_secret_without_secretstring ( ) :
2023-08-24 13:48:53 +00:00
# This test just verifies that Moto does not fail
conn = boto3 . client ( " secretsmanager " , region_name = " us-east-2 " )
2022-11-18 21:18:47 +00:00
conn . create_secret ( Name = DEFAULT_SECRET_NAME , Description = " foodescription " )
2023-08-24 13:48:53 +00:00
# AWS will always require a Lambda ARN to do the actual rotating
2022-11-18 21:18:47 +00:00
rotated_secret = conn . rotate_secret ( SecretId = DEFAULT_SECRET_NAME )
assert rotated_secret [ " Name " ] == DEFAULT_SECRET_NAME
2023-08-24 13:48:53 +00:00
# Without secret-value, and without actual rotating, we can't verify much
# Just that the secret exists/can be described
# We cannot verify any versions info (as that is not created without a secret-value)
2022-11-18 21:18:47 +00:00
describe_secret = conn . describe_secret ( SecretId = DEFAULT_SECRET_NAME )
assert describe_secret [ " Description " ] == " foodescription "
2024-01-07 12:03:33 +00:00
@mock_aws
2018-08-16 00:11:58 +00:00
def test_rotate_secret_enable_rotation ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
2019-05-22 09:45:22 +00:00
conn . create_secret ( Name = DEFAULT_SECRET_NAME , SecretString = " foosecret " )
2018-08-16 00:11:58 +00:00
2019-05-22 09:45:22 +00:00
initial_description = conn . describe_secret ( SecretId = DEFAULT_SECRET_NAME )
2023-08-24 13:48:53 +00:00
assert " RotationEnabled " not in initial_description
2018-08-16 00:11:58 +00:00
2019-05-22 09:45:22 +00:00
conn . rotate_secret (
2018-08-16 00:11:58 +00:00
SecretId = DEFAULT_SECRET_NAME , RotationRules = { " AutomaticallyAfterDays " : 42 }
)
2019-05-22 09:45:22 +00:00
rotated_description = conn . describe_secret ( SecretId = DEFAULT_SECRET_NAME )
2018-08-16 00:11:58 +00:00
assert rotated_description
assert rotated_description [ " RotationEnabled " ] is True
assert rotated_description [ " RotationRules " ] [ " AutomaticallyAfterDays " ] == 42
2019-04-18 15:47:15 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2019-04-18 15:47:15 +00:00
def test_rotate_secret_that_is_marked_deleted ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
conn . create_secret ( Name = " test-secret " , SecretString = " foosecret " )
conn . delete_secret ( SecretId = " test-secret " )
2020-10-06 05:54:49 +00:00
with pytest . raises ( ClientError ) :
2021-10-18 19:44:29 +00:00
conn . rotate_secret ( SecretId = " test-secret " )
2019-04-18 15:47:15 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2018-08-15 17:52:30 +00:00
def test_rotate_secret_that_does_not_exist ( ) :
conn = boto3 . client ( " secretsmanager " , " us-west-2 " )
2020-10-06 05:54:49 +00:00
with pytest . raises ( ClientError ) :
2021-10-18 19:44:29 +00:00
conn . rotate_secret ( SecretId = " i-dont-exist " )
2019-10-31 15:44:26 +00:00
2018-08-15 17:52:30 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2018-08-15 17:52:30 +00:00
def test_rotate_secret_that_does_not_match ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
conn . create_secret ( Name = " test-secret " , SecretString = " foosecret " )
2020-10-06 05:54:49 +00:00
with pytest . raises ( ClientError ) :
2021-10-18 19:44:29 +00:00
conn . rotate_secret ( SecretId = " i-dont-match " )
2019-10-31 15:44:26 +00:00
2018-08-15 18:20:29 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2018-08-15 18:20:29 +00:00
def test_rotate_secret_client_request_token_too_short ( ) :
# Test is intentionally empty. Boto3 catches too short ClientRequestToken
# and raises ParamValidationError before Moto can see it.
# test_server actually handles this error.
assert True
2019-10-31 15:44:26 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2018-08-15 18:20:29 +00:00
def test_rotate_secret_client_request_token_too_long ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
2019-05-22 09:45:22 +00:00
conn . create_secret ( Name = DEFAULT_SECRET_NAME , SecretString = " foosecret " )
2018-08-15 18:20:29 +00:00
client_request_token = (
2023-08-08 10:08:15 +00:00
" ED9F8B6C-85B7-446A-B7E4-38F2A3BEB13C-ED9F8B6C-85B7-446A-B7E4-38F2A3BEB13C "
2018-08-15 18:20:29 +00:00
)
2020-10-06 05:54:49 +00:00
with pytest . raises ( ClientError ) :
2021-10-18 19:44:29 +00:00
conn . rotate_secret (
2018-08-15 18:20:29 +00:00
SecretId = DEFAULT_SECRET_NAME , ClientRequestToken = client_request_token
)
2019-10-31 15:44:26 +00:00
2018-08-15 18:20:29 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2018-08-15 18:20:29 +00:00
def test_rotate_secret_rotation_lambda_arn_too_long ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
2019-05-22 09:45:22 +00:00
conn . create_secret ( Name = DEFAULT_SECRET_NAME , SecretString = " foosecret " )
2018-08-15 18:20:29 +00:00
rotation_lambda_arn = " 85B7-446A-B7E4 " * 147 # == 2058 characters
2020-10-06 05:54:49 +00:00
with pytest . raises ( ClientError ) :
2021-10-18 19:44:29 +00:00
conn . rotate_secret (
2018-08-15 18:20:29 +00:00
SecretId = DEFAULT_SECRET_NAME , RotationLambdaARN = rotation_lambda_arn
)
2019-10-31 15:44:26 +00:00
2018-08-15 18:20:29 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2018-08-15 18:20:29 +00:00
def test_rotate_secret_rotation_period_zero ( ) :
# Test is intentionally empty. Boto3 catches zero day rotation period
# and raises ParamValidationError before Moto can see it.
# test_server actually handles this error.
assert True
2019-08-23 09:57:15 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2018-08-15 18:20:29 +00:00
def test_rotate_secret_rotation_period_too_long ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
2019-05-22 09:45:22 +00:00
conn . create_secret ( Name = DEFAULT_SECRET_NAME , SecretString = " foosecret " )
2018-08-15 18:20:29 +00:00
rotation_rules = { " AutomaticallyAfterDays " : 1001 }
2020-10-06 05:54:49 +00:00
with pytest . raises ( ClientError ) :
2021-10-18 19:44:29 +00:00
conn . rotate_secret ( SecretId = DEFAULT_SECRET_NAME , RotationRules = rotation_rules )
2019-05-22 09:45:22 +00:00
2019-08-23 09:57:15 +00:00
2021-05-11 11:08:01 +00:00
def get_rotation_zip_file ( ) :
2021-09-21 15:19:49 +00:00
from tests . test_awslambda . utilities import _process_lambda
2021-05-11 11:08:01 +00:00
func_str = """
import boto3
import json
def lambda_handler ( event , context ) :
arn = event [ ' SecretId ' ]
token = event [ ' ClientRequestToken ' ]
step = event [ ' Step ' ]
2021-08-03 14:46:23 +00:00
2021-05-11 11:08:01 +00:00
client = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " , endpoint_url = " http://motoserver:5000 " )
metadata = client . describe_secret ( SecretId = arn )
value = client . get_secret_value ( SecretId = arn , VersionId = token , VersionStage = " AWSPENDING " )
if not metadata [ ' RotationEnabled ' ] :
print ( " Secret %s is not enabled for rotation. " % arn )
raise ValueError ( " Secret %s is not enabled for rotation. " % arn )
versions = metadata [ ' VersionIdsToStages ' ]
if token not in versions :
print ( " Secret version %s has no stage for rotation of secret %s . " % ( token , arn ) )
raise ValueError ( " Secret version %s has no stage for rotation of secret %s . " % ( token , arn ) )
if " AWSCURRENT " in versions [ token ] :
print ( " Secret version %s already set as AWSCURRENT for secret %s . " % ( token , arn ) )
return
elif " AWSPENDING " not in versions [ token ] :
print ( " Secret version %s not set as AWSPENDING for rotation of secret %s . " % ( token , arn ) )
raise ValueError ( " Secret version %s not set as AWSPENDING for rotation of secret %s . " % ( token , arn ) )
2021-08-03 14:46:23 +00:00
2021-05-11 11:08:01 +00:00
if step == ' createSecret ' :
try :
client . get_secret_value ( SecretId = arn , VersionId = token , VersionStage = ' AWSPENDING ' )
except client . exceptions . ResourceNotFoundException :
client . put_secret_value (
2021-08-03 14:46:23 +00:00
SecretId = arn ,
ClientRequestToken = token ,
SecretString = json . dumps ( { ' create ' : True } ) ,
2021-05-11 11:08:01 +00:00
VersionStages = [ ' AWSPENDING ' ]
)
if step == ' setSecret ' :
client . put_secret_value (
2021-08-03 14:46:23 +00:00
SecretId = arn ,
ClientRequestToken = token ,
SecretString = ' UpdatedValue ' ,
2021-05-11 11:08:01 +00:00
VersionStages = [ " AWSPENDING " ]
)
2021-08-03 14:46:23 +00:00
2021-05-11 11:08:01 +00:00
elif step == ' finishSecret ' :
current_version = next (
version
for version , stages in metadata [ ' VersionIdsToStages ' ] . items ( )
2021-08-03 14:46:23 +00:00
if ' AWSCURRENT ' in stages
2021-05-11 11:08:01 +00:00
)
print ( " current: %s new: %s " % ( current_version , token ) )
client . update_secret_version_stage (
SecretId = arn ,
VersionStage = ' AWSCURRENT ' ,
MoveToVersionId = token ,
RemoveFromVersionId = current_version
)
client . update_secret_version_stage (
SecretId = arn ,
VersionStage = ' AWSPENDING ' ,
RemoveFromVersionId = token
)
"""
return _process_lambda ( func_str )
if settings . TEST_SERVER_MODE :
2024-01-07 12:03:33 +00:00
@mock_aws
2021-05-11 11:08:01 +00:00
def test_rotate_secret_using_lambda ( ) :
2021-09-21 15:19:49 +00:00
from tests . test_awslambda . utilities import get_role_name
2021-05-11 11:08:01 +00:00
# Passing a `RotationLambdaARN` value to `rotate_secret` should invoke lambda
lambda_conn = boto3 . client (
" lambda " , region_name = " us-west-2 " , endpoint_url = " http://localhost:5000 "
)
func = lambda_conn . create_function (
FunctionName = " testFunction " ,
2023-08-31 06:47:49 +00:00
Runtime = " python3.11 " ,
2021-05-11 11:08:01 +00:00
Role = get_role_name ( ) ,
Handler = " lambda_function.lambda_handler " ,
Code = { " ZipFile " : get_rotation_zip_file ( ) } ,
Description = " Secret rotator " ,
Timeout = 3 ,
MemorySize = 128 ,
Publish = True ,
)
secrets_conn = boto3 . client (
" secretsmanager " ,
region_name = " us-west-2 " ,
endpoint_url = " http://localhost:5000 " ,
)
secret = secrets_conn . create_secret (
Name = DEFAULT_SECRET_NAME , SecretString = " InitialValue "
)
initial_version = secret [ " VersionId " ]
rotated_secret = secrets_conn . rotate_secret (
SecretId = DEFAULT_SECRET_NAME ,
RotationLambdaARN = func [ " FunctionArn " ] ,
2023-08-08 10:08:15 +00:00
RotationRules = { " AutomaticallyAfterDays " : 30 } ,
2021-05-11 11:08:01 +00:00
)
# Ensure we received an updated VersionId from `rotate_secret`
assert rotated_secret [ " VersionId " ] != initial_version
updated_secret = secrets_conn . get_secret_value (
SecretId = DEFAULT_SECRET_NAME , VersionStage = " AWSCURRENT "
)
rotated_version = updated_secret [ " VersionId " ]
assert initial_version != rotated_version
metadata = secrets_conn . describe_secret ( SecretId = DEFAULT_SECRET_NAME )
assert metadata [ " VersionIdsToStages " ] [ initial_version ] == [ " AWSPREVIOUS " ]
assert metadata [ " VersionIdsToStages " ] [ rotated_version ] == [ " AWSCURRENT " ]
assert updated_secret [ " SecretString " ] == " UpdatedValue "
2024-01-07 12:03:33 +00:00
@mock_aws
2020-11-02 10:15:40 +00:00
def test_put_secret_value_on_non_existing_secret ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
2020-11-10 17:14:50 +00:00
with pytest . raises ( ClientError ) as cm :
2020-11-02 10:15:40 +00:00
conn . put_secret_value (
SecretId = DEFAULT_SECRET_NAME ,
SecretString = " foosecret " ,
VersionStages = [ " AWSCURRENT " ] ,
)
2023-08-08 10:08:15 +00:00
assert cm . value . response [ " Error " ] [ " Message " ] == (
2020-11-11 15:55:37 +00:00
" Secrets Manager can ' t find the specified secret. "
)
2020-11-02 10:15:40 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2019-05-22 09:45:22 +00:00
def test_put_secret_value_puts_new_secret ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
2021-07-26 06:40:39 +00:00
conn . create_secret ( Name = DEFAULT_SECRET_NAME , SecretBinary = b " foosecret " )
2019-05-22 09:45:22 +00:00
put_secret_value_dict = conn . put_secret_value (
SecretId = DEFAULT_SECRET_NAME ,
SecretString = " foosecret " ,
VersionStages = [ " AWSCURRENT " ] ,
)
version_id = put_secret_value_dict [ " VersionId " ]
get_secret_value_dict = conn . get_secret_value (
SecretId = DEFAULT_SECRET_NAME , VersionId = version_id , VersionStage = " AWSCURRENT "
)
assert get_secret_value_dict
assert get_secret_value_dict [ " SecretString " ] == " foosecret "
2019-08-23 09:57:15 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2019-08-23 09:57:15 +00:00
def test_put_secret_binary_value_puts_new_secret ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
2021-07-26 06:40:39 +00:00
conn . create_secret ( Name = DEFAULT_SECRET_NAME , SecretBinary = b " foosecret " )
2019-08-23 09:57:15 +00:00
put_secret_value_dict = conn . put_secret_value (
SecretId = DEFAULT_SECRET_NAME ,
2021-07-26 06:40:39 +00:00
SecretBinary = b " foosecret " ,
2019-08-23 09:57:15 +00:00
VersionStages = [ " AWSCURRENT " ] ,
)
version_id = put_secret_value_dict [ " VersionId " ]
get_secret_value_dict = conn . get_secret_value (
SecretId = DEFAULT_SECRET_NAME , VersionId = version_id , VersionStage = " AWSCURRENT "
)
assert get_secret_value_dict
2021-07-26 06:40:39 +00:00
assert get_secret_value_dict [ " SecretBinary " ] == b " foosecret "
2019-08-23 09:57:15 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2019-08-23 09:57:15 +00:00
def test_create_and_put_secret_binary_value_puts_new_secret ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
2021-07-26 06:40:39 +00:00
conn . create_secret ( Name = DEFAULT_SECRET_NAME , SecretBinary = b " foosecret " )
2019-08-23 09:57:15 +00:00
conn . put_secret_value (
2021-07-26 06:40:39 +00:00
SecretId = DEFAULT_SECRET_NAME , SecretBinary = b " foosecret_update "
2019-10-31 15:44:26 +00:00
)
2019-08-23 09:57:15 +00:00
latest_secret = conn . get_secret_value ( SecretId = DEFAULT_SECRET_NAME )
assert latest_secret
2021-07-26 06:40:39 +00:00
assert latest_secret [ " SecretBinary " ] == b " foosecret_update "
2019-08-23 09:57:15 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2019-08-23 09:57:15 +00:00
def test_put_secret_binary_requires_either_string_or_binary ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
2020-10-06 05:54:49 +00:00
with pytest . raises ( ClientError ) as ire :
2019-08-23 09:57:15 +00:00
conn . put_secret_value ( SecretId = DEFAULT_SECRET_NAME )
2023-08-08 10:08:15 +00:00
assert ire . value . response [ " Error " ] [ " Code " ] == " InvalidRequestException "
assert ire . value . response [ " Error " ] [ " Message " ] == (
2019-08-23 09:57:15 +00:00
" You must provide either SecretString or SecretBinary. "
)
2024-01-07 12:03:33 +00:00
@mock_aws
2019-05-22 09:45:22 +00:00
def test_put_secret_value_can_get_first_version_if_put_twice ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
2021-07-26 06:40:39 +00:00
conn . create_secret ( Name = DEFAULT_SECRET_NAME , SecretBinary = b " foosecret " )
2019-05-22 09:45:22 +00:00
put_secret_value_dict = conn . put_secret_value (
SecretId = DEFAULT_SECRET_NAME ,
SecretString = " first_secret " ,
VersionStages = [ " AWSCURRENT " ] ,
)
first_version_id = put_secret_value_dict [ " VersionId " ]
conn . put_secret_value (
SecretId = DEFAULT_SECRET_NAME ,
SecretString = " second_secret " ,
VersionStages = [ " AWSCURRENT " ] ,
)
first_secret_value_dict = conn . get_secret_value (
SecretId = DEFAULT_SECRET_NAME , VersionId = first_version_id
)
first_secret_value = first_secret_value_dict [ " SecretString " ]
assert first_secret_value == " first_secret "
2024-01-07 12:03:33 +00:00
@mock_aws
2019-05-22 09:45:22 +00:00
def test_put_secret_value_versions_differ_if_same_secret_put_twice ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
2020-11-02 10:15:40 +00:00
conn . create_secret ( Name = DEFAULT_SECRET_NAME , SecretBinary = " foosecret " )
2019-05-22 09:45:22 +00:00
put_secret_value_dict = conn . put_secret_value (
SecretId = DEFAULT_SECRET_NAME ,
SecretString = " dupe_secret " ,
VersionStages = [ " AWSCURRENT " ] ,
)
first_version_id = put_secret_value_dict [ " VersionId " ]
put_secret_value_dict = conn . put_secret_value (
SecretId = DEFAULT_SECRET_NAME ,
SecretString = " dupe_secret " ,
VersionStages = [ " AWSCURRENT " ] ,
)
second_version_id = put_secret_value_dict [ " VersionId " ]
assert first_version_id != second_version_id
2024-01-07 12:03:33 +00:00
@mock_aws
2020-04-24 19:47:11 +00:00
def test_put_secret_value_maintains_description_and_tags ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
2020-05-29 11:31:41 +00:00
previous_response = conn . create_secret (
2020-04-24 19:47:11 +00:00
Name = DEFAULT_SECRET_NAME ,
SecretString = " foosecret " ,
Description = " desc " ,
Tags = [ { " Key " : " Foo " , " Value " : " Bar " } , { " Key " : " Mykey " , " Value " : " Myvalue " } ] ,
)
2020-05-29 11:31:41 +00:00
previous_version_id = previous_response [ " VersionId " ]
2020-04-24 19:47:11 +00:00
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
2020-05-29 11:31:41 +00:00
current_response = conn . put_secret_value (
2020-04-24 19:47:11 +00:00
SecretId = DEFAULT_SECRET_NAME ,
SecretString = " dupe_secret " ,
VersionStages = [ " AWSCURRENT " ] ,
)
2020-05-29 11:31:41 +00:00
current_version_id = current_response [ " VersionId " ]
2020-04-24 19:47:11 +00:00
secret_details = conn . describe_secret ( SecretId = DEFAULT_SECRET_NAME )
assert secret_details [ " Tags " ] == [
{ " Key " : " Foo " , " Value " : " Bar " } ,
{ " Key " : " Mykey " , " Value " : " Myvalue " } ,
]
assert secret_details [ " Description " ] == " desc "
2020-05-29 11:31:41 +00:00
assert secret_details [ " VersionIdsToStages " ] is not None
assert previous_version_id in secret_details [ " VersionIdsToStages " ]
assert current_version_id in secret_details [ " VersionIdsToStages " ]
assert secret_details [ " VersionIdsToStages " ] [ previous_version_id ] == [ " AWSPREVIOUS " ]
assert secret_details [ " VersionIdsToStages " ] [ current_version_id ] == [ " AWSCURRENT " ]
2020-04-24 19:47:11 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2019-05-22 09:45:22 +00:00
def test_can_list_secret_version_ids ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
2020-11-02 10:15:40 +00:00
conn . create_secret ( Name = DEFAULT_SECRET_NAME , SecretBinary = " foosecret " )
2019-05-22 09:45:22 +00:00
put_secret_value_dict = conn . put_secret_value (
SecretId = DEFAULT_SECRET_NAME ,
SecretString = " dupe_secret " ,
VersionStages = [ " AWSCURRENT " ] ,
)
first_version_id = put_secret_value_dict [ " VersionId " ]
put_secret_value_dict = conn . put_secret_value (
SecretId = DEFAULT_SECRET_NAME ,
SecretString = " dupe_secret " ,
VersionStages = [ " AWSCURRENT " ] ,
)
second_version_id = put_secret_value_dict [ " VersionId " ]
versions_list = conn . list_secret_version_ids ( SecretId = DEFAULT_SECRET_NAME )
returned_version_ids = [ v [ " VersionId " ] for v in versions_list [ " Versions " ] ]
assert [ first_version_id , second_version_id ] . sort ( ) == returned_version_ids . sort ( )
2020-04-16 15:20:43 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2022-02-11 12:49:14 +00:00
def test_put_secret_value_version_stages_response ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
# Creation.
first_version_id = " eb41453f-25bb-4025-b7f4-850cfca0ce71 "
conn . create_secret (
Name = DEFAULT_SECRET_NAME ,
SecretString = " first_secret_string " ,
ClientRequestToken = first_version_id ,
)
# Use PutSecretValue to push a new version with new version stages.
second_version_id = " eb41453f-25bb-4025-b7f4-850cfca0ce72 "
second_version_stages = [ " SAMPLESTAGE1 " , " SAMPLESTAGE0 " ]
second_put_res_dict = conn . put_secret_value (
SecretId = DEFAULT_SECRET_NAME ,
SecretString = " second_secret_string " ,
VersionStages = second_version_stages ,
ClientRequestToken = second_version_id ,
)
assert second_put_res_dict
assert second_put_res_dict [ " VersionId " ] == second_version_id
assert second_put_res_dict [ " VersionStages " ] == second_version_stages
2024-01-07 12:03:33 +00:00
@mock_aws
2022-02-11 12:49:14 +00:00
def test_put_secret_value_version_stages_pending_response ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
# Creation.
first_version_id = " eb41453f-25bb-4025-b7f4-850cfca0ce71 "
conn . create_secret (
Name = DEFAULT_SECRET_NAME ,
SecretString = " first_secret_string " ,
ClientRequestToken = first_version_id ,
)
# Use PutSecretValue to push a new version with new version stages.
second_version_id = " eb41453f-25bb-4025-b7f4-850cfca0ce72 "
second_version_stages = [ " AWSPENDING " ]
second_put_res_dict = conn . put_secret_value (
SecretId = DEFAULT_SECRET_NAME ,
SecretString = " second_secret_string " ,
VersionStages = second_version_stages ,
ClientRequestToken = second_version_id ,
)
assert second_put_res_dict
assert second_put_res_dict [ " VersionId " ] == second_version_id
assert second_put_res_dict [ " VersionStages " ] == second_version_stages
2024-01-07 12:03:33 +00:00
@mock_aws
2022-02-11 12:49:14 +00:00
def test_after_put_secret_value_version_stages_can_get_current ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
# Creation.
first_version_id = " eb41453f-25bb-4025-b7f4-850cfca0ce71 "
first_secret_string = " first_secret_string "
conn . create_secret (
Name = DEFAULT_SECRET_NAME ,
SecretString = first_secret_string ,
ClientRequestToken = first_version_id ,
)
# Use PutSecretValue to push a new version with new version stages.
second_version_id = " eb41453f-25bb-4025-b7f4-850cfca0ce72 "
conn . put_secret_value (
SecretId = DEFAULT_SECRET_NAME ,
SecretString = " second_secret_string " ,
VersionStages = [ " SAMPLESTAGE1 " , " SAMPLESTAGE0 " ] ,
ClientRequestToken = second_version_id ,
)
# Get current.
get_dict = conn . get_secret_value ( SecretId = DEFAULT_SECRET_NAME )
assert get_dict
assert get_dict [ " VersionId " ] == first_version_id
assert get_dict [ " SecretString " ] == first_secret_string
assert get_dict [ " VersionStages " ] == [ " AWSCURRENT " ]
2024-01-07 12:03:33 +00:00
@mock_aws
2022-03-03 13:02:23 +00:00
def test_after_put_secret_value_version_stages_can_get_current_with_custom_version_stage ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
# Creation.
first_version_id = " eb41453f-25bb-4025-b7f4-850cfca0ce71 "
first_secret_string = " first_secret_string "
conn . create_secret (
Name = DEFAULT_SECRET_NAME ,
SecretString = first_secret_string ,
ClientRequestToken = first_version_id ,
)
# Use PutSecretValue to push a new version with new version stages.
second_version_id = " eb41453f-25bb-4025-b7f4-850cfca0ce72 "
conn . put_secret_value (
SecretId = DEFAULT_SECRET_NAME ,
SecretString = " second_secret_string " ,
VersionStages = [ " SAMPLESTAGE1 " , " SAMPLESTAGE0 " ] ,
ClientRequestToken = second_version_id ,
)
# Create a third version with one of the old stages
third_version_id = " eb41453f-25bb-4025-b7f4-850cfca0ce73 "
third_secret_string = " third_secret_string "
conn . put_secret_value (
SecretId = DEFAULT_SECRET_NAME ,
SecretString = third_secret_string ,
VersionStages = [ " SAMPLESTAGE1 " ] ,
ClientRequestToken = third_version_id ,
)
# Get current with the stage label of the third version.
get_dict = conn . get_secret_value (
SecretId = DEFAULT_SECRET_NAME , VersionStage = " SAMPLESTAGE1 "
)
versions = conn . list_secret_version_ids ( SecretId = DEFAULT_SECRET_NAME ) [ " Versions " ]
versions_by_key = { version [ " VersionId " ] : version for version in versions }
# Check if indeed the third version is returned
assert get_dict
assert get_dict [ " VersionId " ] == third_version_id
assert get_dict [ " SecretString " ] == third_secret_string
assert get_dict [ " VersionStages " ] == [ " SAMPLESTAGE1 " ]
# Check if all the versions have the proper labels
assert versions_by_key [ first_version_id ] [ " VersionStages " ] == [ " AWSCURRENT " ]
assert versions_by_key [ second_version_id ] [ " VersionStages " ] == [ " SAMPLESTAGE0 " ]
assert versions_by_key [ third_version_id ] [ " VersionStages " ] == [ " SAMPLESTAGE1 " ]
2024-01-07 12:03:33 +00:00
@mock_aws
2022-02-11 12:49:14 +00:00
def test_after_put_secret_value_version_stages_pending_can_get_current ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
# Creation.
first_version_id = " eb41453f-25bb-4025-b7f4-850cfca0ce71 "
first_secret_string = " first_secret_string "
conn . create_secret (
Name = DEFAULT_SECRET_NAME ,
SecretString = first_secret_string ,
ClientRequestToken = first_version_id ,
)
# Use PutSecretValue to push a new version with new version stages.
pending_version_id = " eb41453f-25bb-4025-b7f4-850cfca0ce72 "
conn . put_secret_value (
SecretId = DEFAULT_SECRET_NAME ,
SecretString = " second_secret_string " ,
VersionStages = [ " AWSPENDING " ] ,
ClientRequestToken = pending_version_id ,
)
# Get current.
get_dict = conn . get_secret_value ( SecretId = DEFAULT_SECRET_NAME )
assert get_dict
assert get_dict [ " VersionId " ] == first_version_id
assert get_dict [ " SecretString " ] == first_secret_string
assert get_dict [ " VersionStages " ] == [ " AWSCURRENT " ]
2024-01-07 12:03:33 +00:00
@mock_aws
2021-09-27 19:59:13 +00:00
@pytest.mark.parametrize ( " pass_arn " , [ True , False ] )
def test_update_secret ( pass_arn ) :
2020-04-16 15:20:43 +00:00
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
created_secret = conn . create_secret ( Name = " test-secret " , SecretString = " foosecret " )
assert created_secret [ " ARN " ]
assert created_secret [ " Name " ] == " test-secret "
assert created_secret [ " VersionId " ] != " "
2021-09-27 19:59:13 +00:00
secret_id = created_secret [ " ARN " ] if pass_arn else " test-secret "
secret = conn . get_secret_value ( SecretId = secret_id )
2020-04-16 15:20:43 +00:00
assert secret [ " SecretString " ] == " foosecret "
2023-05-31 23:09:08 +00:00
updated_secret = conn . update_secret (
SecretId = secret_id ,
SecretString = " barsecret " ,
Description = " new desc " ,
)
2020-04-16 15:20:43 +00:00
assert updated_secret [ " ARN " ]
assert updated_secret [ " Name " ] == " test-secret "
assert updated_secret [ " VersionId " ] != " "
2021-09-27 19:59:13 +00:00
secret = conn . get_secret_value ( SecretId = secret_id )
2020-04-16 15:20:43 +00:00
assert secret [ " SecretString " ] == " barsecret "
assert created_secret [ " VersionId " ] != updated_secret [ " VersionId " ]
2023-05-31 23:09:08 +00:00
assert conn . describe_secret ( SecretId = secret_id ) [ " Description " ] == " new desc "
2020-04-16 15:20:43 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2022-01-25 10:24:26 +00:00
@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 " ]
)
2024-01-07 12:03:33 +00:00
@mock_aws
2020-04-24 19:47:11 +00:00
def test_update_secret_with_tags_and_description ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
created_secret = conn . create_secret (
Name = " test-secret " ,
SecretString = " foosecret " ,
Description = " desc " ,
Tags = [ { " Key " : " Foo " , " Value " : " Bar " } , { " Key " : " Mykey " , " Value " : " Myvalue " } ] ,
)
assert created_secret [ " ARN " ]
assert created_secret [ " Name " ] == " test-secret "
assert created_secret [ " VersionId " ] != " "
secret = conn . get_secret_value ( SecretId = " test-secret " )
assert secret [ " SecretString " ] == " foosecret "
updated_secret = conn . update_secret (
SecretId = " test-secret " , SecretString = " barsecret "
)
assert updated_secret [ " ARN " ]
assert updated_secret [ " Name " ] == " test-secret "
assert updated_secret [ " VersionId " ] != " "
secret = conn . get_secret_value ( SecretId = " test-secret " )
assert secret [ " SecretString " ] == " barsecret "
assert created_secret [ " VersionId " ] != updated_secret [ " VersionId " ]
secret_details = conn . describe_secret ( SecretId = " test-secret " )
assert secret_details [ " Tags " ] == [
{ " Key " : " Foo " , " Value " : " Bar " } ,
{ " Key " : " Mykey " , " Value " : " Myvalue " } ,
]
assert secret_details [ " Description " ] == " desc "
2024-01-07 12:03:33 +00:00
@mock_aws
2021-08-03 14:46:23 +00:00
def test_update_secret_with_KmsKeyId ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
created_secret = conn . create_secret (
Name = " test-secret " , SecretString = " foosecret " , KmsKeyId = " foo_arn "
)
assert created_secret [ " ARN " ]
assert created_secret [ " Name " ] == " test-secret "
assert created_secret [ " VersionId " ] != " "
secret = conn . get_secret_value ( SecretId = " test-secret " )
assert secret [ " SecretString " ] == " foosecret "
secret_details = conn . describe_secret ( SecretId = " test-secret " )
2023-08-08 10:08:15 +00:00
assert secret_details [ " KmsKeyId " ] == " foo_arn "
2021-08-03 14:46:23 +00:00
updated_secret = conn . update_secret (
SecretId = " test-secret " , SecretString = " barsecret " , KmsKeyId = " bar_arn "
)
assert updated_secret [ " ARN " ]
assert updated_secret [ " Name " ] == " test-secret "
assert updated_secret [ " VersionId " ] != " "
secret = conn . get_secret_value ( SecretId = " test-secret " )
assert secret [ " SecretString " ] == " barsecret "
assert created_secret [ " VersionId " ] != updated_secret [ " VersionId " ]
secret_details = conn . describe_secret ( SecretId = " test-secret " )
2023-08-08 10:08:15 +00:00
assert secret_details [ " KmsKeyId " ] == " bar_arn "
2021-08-03 14:46:23 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2020-04-16 15:20:43 +00:00
def test_update_secret_which_does_not_exit ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
2020-10-06 05:54:49 +00:00
with pytest . raises ( ClientError ) as cm :
2021-10-18 19:44:29 +00:00
conn . update_secret ( SecretId = " test-secret " , SecretString = " barsecret " )
2020-04-16 15:20:43 +00:00
2020-10-06 06:46:05 +00:00
assert (
" Secrets Manager can ' t find the specified secret. "
== cm . value . response [ " Error " ] [ " Message " ]
)
2020-04-16 15:20:43 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2020-04-16 15:20:43 +00:00
def test_update_secret_marked_as_deleted ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
2021-10-18 19:44:29 +00:00
conn . create_secret ( Name = " test-secret " , SecretString = " foosecret " )
conn . delete_secret ( SecretId = " test-secret " )
2020-04-16 15:20:43 +00:00
2020-10-06 05:54:49 +00:00
with pytest . raises ( ClientError ) as cm :
2021-10-18 19:44:29 +00:00
conn . update_secret ( SecretId = " test-secret " , SecretString = " barsecret " )
2020-04-16 15:20:43 +00:00
assert (
2020-10-06 06:46:05 +00:00
" because it was marked for deletion. " in cm . value . response [ " Error " ] [ " Message " ]
2020-04-16 15:20:43 +00:00
)
2024-01-07 12:03:33 +00:00
@mock_aws
2020-04-16 15:20:43 +00:00
def test_update_secret_marked_as_deleted_after_restoring ( ) :
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
2021-10-18 19:44:29 +00:00
conn . create_secret ( Name = " test-secret " , SecretString = " foosecret " )
conn . delete_secret ( SecretId = " test-secret " )
conn . restore_secret ( SecretId = " test-secret " )
2020-04-16 15:20:43 +00:00
updated_secret = conn . update_secret (
SecretId = " test-secret " , SecretString = " barsecret "
)
assert updated_secret [ " ARN " ]
assert updated_secret [ " Name " ] == " test-secret "
assert updated_secret [ " VersionId " ] != " "
2020-10-22 10:14:32 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2021-09-27 19:59:13 +00:00
@pytest.mark.parametrize ( " pass_arn " , [ True , False ] )
def test_tag_resource ( pass_arn ) :
2020-10-22 10:14:32 +00:00
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
2021-09-27 19:59:13 +00:00
created_secret = conn . create_secret ( Name = " test-secret " , SecretString = " foosecret " )
secret_id = created_secret [ " ARN " ] if pass_arn else " test-secret "
2020-10-22 10:14:32 +00:00
conn . tag_resource (
2021-09-27 19:59:13 +00:00
SecretId = secret_id , Tags = [ { " Key " : " FirstTag " , " Value " : " SomeValue " } ]
2020-10-22 10:14:32 +00:00
)
2022-03-01 22:50:42 +00:00
conn . tag_resource (
SecretId = " test-secret " , Tags = [ { " Key " : " FirstTag " , " Value " : " SomeOtherValue " } ]
)
2020-10-22 10:14:32 +00:00
conn . tag_resource (
2021-09-27 19:59:13 +00:00
SecretId = secret_id , Tags = [ { " Key " : " SecondTag " , " Value " : " AnotherValue " } ]
2020-10-22 10:14:32 +00:00
)
secrets = conn . list_secrets ( )
assert secrets [ " SecretList " ] [ 0 ] . get ( " Tags " ) == [
2022-03-01 22:50:42 +00:00
{ " Key " : " FirstTag " , " Value " : " SomeOtherValue " } ,
2020-10-22 10:14:32 +00:00
{ " Key " : " SecondTag " , " Value " : " AnotherValue " } ,
]
2020-11-10 17:14:50 +00:00
with pytest . raises ( ClientError ) as cm :
2020-10-22 10:14:32 +00:00
conn . tag_resource (
SecretId = " dummy-test-secret " ,
2020-11-11 15:55:37 +00:00
Tags = [ { " Key " : " FirstTag " , " Value " : " SomeValue " } ] ,
2020-10-22 10:14:32 +00:00
)
2020-11-11 15:55:37 +00:00
assert (
" Secrets Manager can ' t find the specified secret. "
== cm . value . response [ " Error " ] [ " Message " ]
)
2020-11-03 14:18:56 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2021-09-27 19:59:13 +00:00
@pytest.mark.parametrize ( " pass_arn " , [ True , False ] )
def test_untag_resource ( pass_arn ) :
2021-03-12 10:35:38 +00:00
conn = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
2021-09-27 19:59:13 +00:00
created_secret = conn . create_secret ( Name = " test-secret " , SecretString = " foosecret " )
secret_id = created_secret [ " ARN " ] if pass_arn else " test-secret "
2021-03-12 10:35:38 +00:00
conn . tag_resource (
2021-09-27 19:59:13 +00:00
SecretId = secret_id ,
2021-03-12 10:35:38 +00:00
Tags = [
{ " Key " : " FirstTag " , " Value " : " SomeValue " } ,
{ " Key " : " SecondTag " , " Value " : " SomeValue " } ,
] ,
)
2021-09-27 19:59:13 +00:00
conn . untag_resource ( SecretId = secret_id , TagKeys = [ " FirstTag " ] )
2021-03-12 10:35:38 +00:00
secrets = conn . list_secrets ( )
assert secrets [ " SecretList " ] [ 0 ] . get ( " Tags " ) == [
{ " Key " : " SecondTag " , " Value " : " SomeValue " } ,
]
with pytest . raises ( ClientError ) as cm :
conn . untag_resource ( SecretId = " dummy-test-secret " , TagKeys = [ " FirstTag " ] )
assert (
" Secrets Manager can ' t find the specified secret. "
== cm . value . response [ " Error " ] [ " Message " ]
)
2024-01-07 12:03:33 +00:00
@mock_aws
2020-11-03 14:18:56 +00:00
def test_secret_versions_to_stages_attribute_discrepancy ( ) :
client = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
resp = client . create_secret ( Name = DEFAULT_SECRET_NAME , SecretString = " foosecret " )
previous_version_id = resp [ " VersionId " ]
resp = client . put_secret_value (
SecretId = DEFAULT_SECRET_NAME ,
SecretString = " dupe_secret " ,
VersionStages = [ " AWSCURRENT " ] ,
)
current_version_id = resp [ " VersionId " ]
secret = client . describe_secret ( SecretId = DEFAULT_SECRET_NAME )
describe_vtos = secret [ " VersionIdsToStages " ]
assert describe_vtos [ current_version_id ] == [ " AWSCURRENT " ]
assert describe_vtos [ previous_version_id ] == [ " AWSPREVIOUS " ]
secret = client . list_secrets (
Filters = [ { " Key " : " name " , " Values " : [ DEFAULT_SECRET_NAME ] } ]
) . get ( " SecretList " ) [ 0 ]
list_vtos = secret [ " SecretVersionsToStages " ]
assert list_vtos [ current_version_id ] == [ " AWSCURRENT " ]
assert list_vtos [ previous_version_id ] == [ " AWSPREVIOUS " ]
assert describe_vtos == list_vtos
2021-09-21 16:43:31 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2021-09-21 16:43:31 +00:00
def test_update_secret_with_client_request_token ( ) :
client = boto3 . client ( " secretsmanager " , region_name = " us-west-2 " )
secret_name = " test-secret "
client_request_token = str ( uuid4 ( ) )
client . create_secret ( Name = secret_name , SecretString = " first-secret " )
updated_secret = client . update_secret (
SecretId = secret_name ,
SecretString = " second-secret " ,
ClientRequestToken = client_request_token ,
)
assert client_request_token == updated_secret [ " VersionId " ]
updated_secret = client . update_secret (
SecretId = secret_name , SecretString = " third-secret "
)
assert client_request_token != updated_secret [ " VersionId " ]
invalid_request_token = " test-token "
with pytest . raises ( ParamValidationError ) as pve :
client . update_secret (
SecretId = secret_name ,
SecretString = " fourth-secret " ,
ClientRequestToken = invalid_request_token ,
)
2023-08-08 10:08:15 +00:00
assert pve . value . response [ " Error " ] [ " Code " ] == " InvalidParameterException "
assert pve . value . response [ " Error " ] [ " Message " ] == (
2021-09-21 16:43:31 +00:00
" ClientRequestToken must be 32-64 characters long. "
)
2024-03-07 21:22:13 +00:00
@secretsmanager_aws_verified
@pytest.mark.aws_verified
def test_update_secret_version_stage_manually ( secret_arn = None ) :
sm_client = boto3 . client ( " secretsmanager " , " us-east-1 " )
current_version = sm_client . put_secret_value (
SecretId = secret_arn ,
SecretString = " previous_secret " ,
VersionStages = [ " AWSCURRENT " ] ,
) [ " VersionId " ]
initial_secret = sm_client . get_secret_value (
SecretId = secret_arn , VersionStage = " AWSCURRENT "
)
assert initial_secret [ " VersionStages " ] == [ " AWSCURRENT " ]
assert initial_secret [ " SecretString " ] == " previous_secret "
token = str ( uuid4 ( ) )
sm_client . put_secret_value (
SecretId = secret_arn ,
ClientRequestToken = token ,
SecretString = " new_secret " ,
VersionStages = [ " AWSPENDING " ] ,
)
pending_secret = sm_client . get_secret_value (
SecretId = secret_arn , VersionStage = " AWSPENDING "
)
assert pending_secret [ " VersionStages " ] == [ " AWSPENDING " ]
assert pending_secret [ " SecretString " ] == " new_secret "
sm_client . update_secret_version_stage (
SecretId = secret_arn ,
VersionStage = " AWSCURRENT " ,
MoveToVersionId = token ,
RemoveFromVersionId = current_version ,
)
current_secret = sm_client . get_secret_value (
SecretId = secret_arn , VersionStage = " AWSCURRENT "
)
assert list ( sorted ( current_secret [ " VersionStages " ] ) ) == [ " AWSCURRENT " , " AWSPENDING " ]
assert current_secret [ " SecretString " ] == " new_secret "
previous_secret = sm_client . get_secret_value (
SecretId = secret_arn , VersionStage = " AWSPREVIOUS "
)
assert previous_secret [ " VersionStages " ] == [ " AWSPREVIOUS " ]
assert previous_secret [ " SecretString " ] == " previous_secret "
@secretsmanager_aws_verified
@pytest.mark.aws_verified
def test_update_secret_version_stage_dont_specify_current_stage ( secret_arn = None ) :
sm_client = boto3 . client ( " secretsmanager " , " us-east-1 " )
current_version = sm_client . put_secret_value (
SecretId = secret_arn ,
SecretString = " previous_secret " ,
VersionStages = [ " AWSCURRENT " ] ,
) [ " VersionId " ]
token = str ( uuid4 ( ) )
sm_client . put_secret_value (
SecretId = secret_arn ,
ClientRequestToken = token ,
SecretString = " new_secret " ,
VersionStages = [ " AWSPENDING " ] ,
)
# Without specifying version that currently has stage AWSCURRENT
with pytest . raises ( ClientError ) as exc :
sm_client . update_secret_version_stage (
SecretId = secret_arn , VersionStage = " AWSCURRENT " , MoveToVersionId = token
)
err = exc . value . response [ " Error " ]
assert err [ " Code " ] == " InvalidParameterException "
assert (
err [ " Message " ]
== f " The parameter RemoveFromVersionId can ' t be empty. Staging label AWSCURRENT is currently attached to version { current_version } , so you must explicitly reference that version in RemoveFromVersionId. "
)