Update get_secret_value to properly check versions and stages match (#5238)
This commit is contained in:
		
							parent
							
								
									58edb5b840
								
							
						
					
					
						commit
						836a2e6538
					
				| @ -30,6 +30,15 @@ class SecretHasNoValueException(SecretsManagerClientError): | |||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | class SecretStageVersionMismatchException(SecretsManagerClientError): | ||||||
|  |     def __init__(self): | ||||||
|  |         self.code = 404 | ||||||
|  |         super().__init__( | ||||||
|  |             "InvalidRequestException", | ||||||
|  |             message="You provided a VersionStage that is not associated to the provided VersionId.", | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| class ClientError(SecretsManagerClientError): | class ClientError(SecretsManagerClientError): | ||||||
|     def __init__(self, message): |     def __init__(self, message): | ||||||
|         super().__init__("InvalidParameterValue", message) |         super().__init__("InvalidParameterValue", message) | ||||||
|  | |||||||
| @ -13,6 +13,7 @@ from .exceptions import ( | |||||||
|     InvalidParameterException, |     InvalidParameterException, | ||||||
|     ResourceExistsException, |     ResourceExistsException, | ||||||
|     ResourceNotFoundException, |     ResourceNotFoundException, | ||||||
|  |     SecretStageVersionMismatchException, | ||||||
|     InvalidRequestException, |     InvalidRequestException, | ||||||
|     ClientError, |     ClientError, | ||||||
| ) | ) | ||||||
| @ -226,6 +227,14 @@ class SecretsManagerBackend(BaseBackend): | |||||||
|         if not self._is_valid_identifier(secret_id): |         if not self._is_valid_identifier(secret_id): | ||||||
|             raise SecretNotFoundException() |             raise SecretNotFoundException() | ||||||
| 
 | 
 | ||||||
|  |         if version_id and version_stage: | ||||||
|  |             versions_dict = self.secrets[secret_id].versions | ||||||
|  |             if ( | ||||||
|  |                 version_id in versions_dict | ||||||
|  |                 and version_stage not in versions_dict[version_id]["version_stages"] | ||||||
|  |             ): | ||||||
|  |                 raise SecretStageVersionMismatchException() | ||||||
|  | 
 | ||||||
|         if not version_id and version_stage: |         if not version_id and version_stage: | ||||||
|             # set version_id to match version_stage |             # set version_id to match version_stage | ||||||
|             versions_dict = self.secrets[secret_id].versions |             versions_dict = self.secrets[secret_id].versions | ||||||
|  | |||||||
| @ -153,6 +153,33 @@ def test_get_secret_version_that_does_not_exist(): | |||||||
|     ) == cm.value.response["Error"]["Message"] |     ) == cm.value.response["Error"]["Message"] | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @mock_secretsmanager | ||||||
|  | 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"] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| @mock_secretsmanager | @mock_secretsmanager | ||||||
| def test_create_secret(): | def test_create_secret(): | ||||||
|     conn = boto3.client("secretsmanager", region_name="us-east-1") |     conn = boto3.client("secretsmanager", region_name="us-east-1") | ||||||
|  | |||||||
| @ -618,7 +618,7 @@ def test_put_secret_value_can_get_first_version_if_put_twice(): | |||||||
|         data={ |         data={ | ||||||
|             "SecretId": DEFAULT_SECRET_NAME, |             "SecretId": DEFAULT_SECRET_NAME, | ||||||
|             "VersionId": first_secret_version_id, |             "VersionId": first_secret_version_id, | ||||||
|             "VersionStage": "AWSCURRENT", |             "VersionStage": "AWSPREVIOUS", | ||||||
|         }, |         }, | ||||||
|         headers={"X-Amz-Target": "secretsmanager.GetSecretValue"}, |         headers={"X-Amz-Target": "secretsmanager.GetSecretValue"}, | ||||||
|     ) |     ) | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user