Added support for EMR Security Configurations and Kerberos Attributes. (#3456)
* Added support for EMR Security Configurations and Kerberos Attributes. * Revised exception-raising test to work with pytest api. * Added htmlcov to .gitignore; upgrading botocore to 1.18.17, per commit d29475e. Co-authored-by: Joseph Weitekamp <jweite@amazon.com>
This commit is contained in:
		
							parent
							
								
									f045af7e0a
								
							
						
					
					
						commit
						5fe921c2bc
					
				
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -23,3 +23,4 @@ tests/file.tmp | |||||||
| .mypy_cache/ | .mypy_cache/ | ||||||
| *.tmp | *.tmp | ||||||
| .venv/ | .venv/ | ||||||
|  | htmlcov/ | ||||||
| @ -1,7 +1,14 @@ | |||||||
| from __future__ import unicode_literals | from __future__ import unicode_literals | ||||||
| 
 | 
 | ||||||
| from moto.core.exceptions import RESTError | from moto.core.exceptions import RESTError, JsonRESTError | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class EmrError(RESTError): | class EmrError(RESTError): | ||||||
|     code = 400 |     code = 400 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class InvalidRequestException(JsonRESTError): | ||||||
|  |     def __init__(self, message, **kwargs): | ||||||
|  |         super(InvalidRequestException, self).__init__( | ||||||
|  |             "InvalidRequestException", message, **kwargs | ||||||
|  |         ) | ||||||
|  | |||||||
| @ -6,7 +6,7 @@ import pytz | |||||||
| from boto3 import Session | from boto3 import Session | ||||||
| from dateutil.parser import parse as dtparse | from dateutil.parser import parse as dtparse | ||||||
| from moto.core import BaseBackend, BaseModel | from moto.core import BaseBackend, BaseModel | ||||||
| from moto.emr.exceptions import EmrError | from moto.emr.exceptions import EmrError, InvalidRequestException | ||||||
| from .utils import ( | from .utils import ( | ||||||
|     random_instance_group_id, |     random_instance_group_id, | ||||||
|     random_cluster_id, |     random_cluster_id, | ||||||
| @ -147,6 +147,8 @@ class FakeCluster(BaseModel): | |||||||
|         running_ami_version=None, |         running_ami_version=None, | ||||||
|         custom_ami_id=None, |         custom_ami_id=None, | ||||||
|         step_concurrency_level=1, |         step_concurrency_level=1, | ||||||
|  |         security_configuration=None, | ||||||
|  |         kerberos_attributes=None, | ||||||
|     ): |     ): | ||||||
|         self.id = cluster_id or random_cluster_id() |         self.id = cluster_id or random_cluster_id() | ||||||
|         emr_backend.clusters[self.id] = self |         emr_backend.clusters[self.id] = self | ||||||
| @ -249,6 +251,10 @@ class FakeCluster(BaseModel): | |||||||
|         self.run_bootstrap_actions() |         self.run_bootstrap_actions() | ||||||
|         if self.steps: |         if self.steps: | ||||||
|             self.steps[0].start() |             self.steps[0].start() | ||||||
|  |         self.security_configuration = ( | ||||||
|  |             security_configuration  # ToDo: Raise if doesn't already exist. | ||||||
|  |         ) | ||||||
|  |         self.kerberos_attributes = kerberos_attributes | ||||||
| 
 | 
 | ||||||
|     @property |     @property | ||||||
|     def instance_groups(self): |     def instance_groups(self): | ||||||
| @ -337,12 +343,20 @@ class FakeCluster(BaseModel): | |||||||
|         self.visible_to_all_users = visibility |         self.visible_to_all_users = visibility | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | class FakeSecurityConfiguration(BaseModel): | ||||||
|  |     def __init__(self, name, security_configuration): | ||||||
|  |         self.name = name | ||||||
|  |         self.security_configuration = security_configuration | ||||||
|  |         self.creation_date_time = datetime.now(pytz.utc) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| class ElasticMapReduceBackend(BaseBackend): | class ElasticMapReduceBackend(BaseBackend): | ||||||
|     def __init__(self, region_name): |     def __init__(self, region_name): | ||||||
|         super(ElasticMapReduceBackend, self).__init__() |         super(ElasticMapReduceBackend, self).__init__() | ||||||
|         self.region_name = region_name |         self.region_name = region_name | ||||||
|         self.clusters = {} |         self.clusters = {} | ||||||
|         self.instance_groups = {} |         self.instance_groups = {} | ||||||
|  |         self.security_configurations = {} | ||||||
| 
 | 
 | ||||||
|     def reset(self): |     def reset(self): | ||||||
|         region_name = self.region_name |         region_name = self.region_name | ||||||
| @ -527,6 +541,37 @@ class ElasticMapReduceBackend(BaseBackend): | |||||||
|         instance_group = instance_groups[0] |         instance_group = instance_groups[0] | ||||||
|         instance_group.auto_scaling_policy = None |         instance_group.auto_scaling_policy = None | ||||||
| 
 | 
 | ||||||
|  |     def create_security_configuration(self, name, security_configuration): | ||||||
|  |         if name in self.security_configurations: | ||||||
|  |             raise InvalidRequestException( | ||||||
|  |                 message="SecurityConfiguration with name '{}' already exists.".format( | ||||||
|  |                     name | ||||||
|  |                 ) | ||||||
|  |             ) | ||||||
|  |         security_configuration = FakeSecurityConfiguration( | ||||||
|  |             name=name, security_configuration=security_configuration | ||||||
|  |         ) | ||||||
|  |         self.security_configurations[name] = security_configuration | ||||||
|  |         return security_configuration | ||||||
|  | 
 | ||||||
|  |     def get_security_configuration(self, name): | ||||||
|  |         if name not in self.security_configurations: | ||||||
|  |             raise InvalidRequestException( | ||||||
|  |                 message="Security configuration with name '{}' does not exist.".format( | ||||||
|  |                     name | ||||||
|  |                 ) | ||||||
|  |             ) | ||||||
|  |         return self.security_configurations[name] | ||||||
|  | 
 | ||||||
|  |     def delete_security_configuration(self, name): | ||||||
|  |         if name not in self.security_configurations: | ||||||
|  |             raise InvalidRequestException( | ||||||
|  |                 message="Security configuration with name '{}' does not exist.".format( | ||||||
|  |                     name | ||||||
|  |                 ) | ||||||
|  |             ) | ||||||
|  |         del self.security_configurations[name] | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| emr_backends = {} | emr_backends = {} | ||||||
| for region in Session().get_available_regions("emr"): | for region in Session().get_available_regions("emr"): | ||||||
|  | |||||||
| @ -102,11 +102,29 @@ class ElasticMapReduceResponse(BaseResponse): | |||||||
|     def cancel_steps(self): |     def cancel_steps(self): | ||||||
|         raise NotImplementedError |         raise NotImplementedError | ||||||
| 
 | 
 | ||||||
|  |     @generate_boto3_response("CreateSecurityConfiguration") | ||||||
|     def create_security_configuration(self): |     def create_security_configuration(self): | ||||||
|         raise NotImplementedError |         name = self._get_param("Name") | ||||||
|  |         security_configuration = self._get_param("SecurityConfiguration") | ||||||
|  |         resp = self.backend.create_security_configuration( | ||||||
|  |             name=name, security_configuration=security_configuration | ||||||
|  |         ) | ||||||
|  |         template = self.response_template(CREATE_SECURITY_CONFIGURATION_TEMPLATE) | ||||||
|  |         return template.render(name=name, creation_date_time=resp.creation_date_time) | ||||||
| 
 | 
 | ||||||
|  |     @generate_boto3_response("DescribeSecurityConfiguration") | ||||||
|  |     def describe_security_configuration(self): | ||||||
|  |         name = self._get_param("Name") | ||||||
|  |         security_configuration = self.backend.get_security_configuration(name=name) | ||||||
|  |         template = self.response_template(DESCRIBE_SECURITY_CONFIGURATION_TEMPLATE) | ||||||
|  |         return template.render(security_configuration=security_configuration) | ||||||
|  | 
 | ||||||
|  |     @generate_boto3_response("DeleteSecurityConfiguration") | ||||||
|     def delete_security_configuration(self): |     def delete_security_configuration(self): | ||||||
|         raise NotImplementedError |         name = self._get_param("Name") | ||||||
|  |         self.backend.delete_security_configuration(name=name) | ||||||
|  |         template = self.response_template(DELETE_SECURITY_CONFIGURATION_TEMPLATE) | ||||||
|  |         return template.render() | ||||||
| 
 | 
 | ||||||
|     @generate_boto3_response("DescribeCluster") |     @generate_boto3_response("DescribeCluster") | ||||||
|     def describe_cluster(self): |     def describe_cluster(self): | ||||||
| @ -190,9 +208,6 @@ class ElasticMapReduceResponse(BaseResponse): | |||||||
|         template = self.response_template(MODIFY_CLUSTER_TEMPLATE) |         template = self.response_template(MODIFY_CLUSTER_TEMPLATE) | ||||||
|         return template.render(cluster=cluster) |         return template.render(cluster=cluster) | ||||||
| 
 | 
 | ||||||
|     def describe_security_configuration(self): |  | ||||||
|         raise NotImplementedError |  | ||||||
| 
 |  | ||||||
|     @generate_boto3_response("ModifyInstanceGroups") |     @generate_boto3_response("ModifyInstanceGroups") | ||||||
|     def modify_instance_groups(self): |     def modify_instance_groups(self): | ||||||
|         instance_groups = self._get_list_prefix("InstanceGroups.member") |         instance_groups = self._get_list_prefix("InstanceGroups.member") | ||||||
| @ -327,6 +342,39 @@ class ElasticMapReduceResponse(BaseResponse): | |||||||
|         if step_concurrency_level: |         if step_concurrency_level: | ||||||
|             kwargs["step_concurrency_level"] = step_concurrency_level |             kwargs["step_concurrency_level"] = step_concurrency_level | ||||||
| 
 | 
 | ||||||
|  |         security_configuration = self._get_param("SecurityConfiguration") | ||||||
|  |         if security_configuration: | ||||||
|  |             kwargs["security_configuration"] = security_configuration | ||||||
|  | 
 | ||||||
|  |         kerberos_attributes = {} | ||||||
|  |         kwargs["kerberos_attributes"] = kerberos_attributes | ||||||
|  | 
 | ||||||
|  |         realm = self._get_param("KerberosAttributes.Realm") | ||||||
|  |         if realm: | ||||||
|  |             kerberos_attributes["Realm"] = realm | ||||||
|  | 
 | ||||||
|  |         kdc_admin_password = self._get_param("KerberosAttributes.KdcAdminPassword") | ||||||
|  |         if kdc_admin_password: | ||||||
|  |             kerberos_attributes["KdcAdminPassword"] = kdc_admin_password | ||||||
|  | 
 | ||||||
|  |         cross_realm_principal_password = self._get_param( | ||||||
|  |             "KerberosAttributes.CrossRealmTrustPrincipalPassword" | ||||||
|  |         ) | ||||||
|  |         if cross_realm_principal_password: | ||||||
|  |             kerberos_attributes[ | ||||||
|  |                 "CrossRealmTrustPrincipalPassword" | ||||||
|  |             ] = cross_realm_principal_password | ||||||
|  | 
 | ||||||
|  |         ad_domain_join_user = self._get_param("KerberosAttributes.ADDomainJoinUser") | ||||||
|  |         if ad_domain_join_user: | ||||||
|  |             kerberos_attributes["ADDomainJoinUser"] = ad_domain_join_user | ||||||
|  | 
 | ||||||
|  |         ad_domain_join_password = self._get_param( | ||||||
|  |             "KerberosAttributes.ADDomainJoinPassword" | ||||||
|  |         ) | ||||||
|  |         if ad_domain_join_password: | ||||||
|  |             kerberos_attributes["ADDomainJoinPassword"] = ad_domain_join_password | ||||||
|  | 
 | ||||||
|         cluster = self.backend.run_job_flow(**kwargs) |         cluster = self.backend.run_job_flow(**kwargs) | ||||||
| 
 | 
 | ||||||
|         applications = self._get_list_prefix("Applications.member") |         applications = self._get_list_prefix("Applications.member") | ||||||
| @ -560,6 +608,23 @@ DESCRIBE_CLUSTER_TEMPLATE = """<DescribeClusterResponse xmlns="http://elasticmap | |||||||
|         <ServiceAccessSecurityGroup>{{ cluster.service_access_security_group }}</ServiceAccessSecurityGroup> |         <ServiceAccessSecurityGroup>{{ cluster.service_access_security_group }}</ServiceAccessSecurityGroup> | ||||||
|       </Ec2InstanceAttributes> |       </Ec2InstanceAttributes> | ||||||
|       <Id>{{ cluster.id }}</Id> |       <Id>{{ cluster.id }}</Id> | ||||||
|  |       <KerberosAttributes> | ||||||
|  |         {% if 'Realm' in cluster.kerberos_attributes%} | ||||||
|  |         <Realm>{{ cluster.kerberos_attributes['Realm'] }}</Realm> | ||||||
|  |         {% endif %} | ||||||
|  |         {% if 'KdcAdminPassword' in cluster.kerberos_attributes%} | ||||||
|  |         <KdcAdminPassword>{{ cluster.kerberos_attributes['KdcAdminPassword'] }}</KdcAdminPassword> | ||||||
|  |         {% endif %} | ||||||
|  |         {% if 'CrossRealmTrustPrincipalPassword' in cluster.kerberos_attributes%} | ||||||
|  |         <CrossRealmTrustPrincipalPassword>{{ cluster.kerberos_attributes['CrossRealmTrustPrincipalPassword'] }}</CrossRealmTrustPrincipalPassword> | ||||||
|  |         {% endif %} | ||||||
|  |         {% if 'ADDomainJoinUser' in cluster.kerberos_attributes%} | ||||||
|  |         <ADDomainJoinUser>{{ cluster.kerberos_attributes['ADDomainJoinUser'] }}</ADDomainJoinUser> | ||||||
|  |         {% endif %} | ||||||
|  |         {% if 'ADDomainJoinPassword' in cluster.kerberos_attributes%} | ||||||
|  |         <ADDomainJoinPassword>{{ cluster.kerberos_attributes['ADDomainJoinPassword'] }}</ADDomainJoinPassword> | ||||||
|  |         {% endif %} | ||||||
|  |       </KerberosAttributes> | ||||||
|       <LogUri>{{ cluster.log_uri }}</LogUri> |       <LogUri>{{ cluster.log_uri }}</LogUri> | ||||||
|       <MasterPublicDnsName>ec2-184-0-0-1.us-west-1.compute.amazonaws.com</MasterPublicDnsName> |       <MasterPublicDnsName>ec2-184-0-0-1.us-west-1.compute.amazonaws.com</MasterPublicDnsName> | ||||||
|       <Name>{{ cluster.name }}</Name> |       <Name>{{ cluster.name }}</Name> | ||||||
| @ -573,7 +638,9 @@ DESCRIBE_CLUSTER_TEMPLATE = """<DescribeClusterResponse xmlns="http://elasticmap | |||||||
|       {% if cluster.running_ami_version is not none %} |       {% if cluster.running_ami_version is not none %} | ||||||
|       <RunningAmiVersion>{{ cluster.running_ami_version }}</RunningAmiVersion> |       <RunningAmiVersion>{{ cluster.running_ami_version }}</RunningAmiVersion> | ||||||
|       {% endif %} |       {% endif %} | ||||||
|       <SecurityConfiguration/> |       {% if cluster.security_configuration is not none %} | ||||||
|  |       <SecurityConfiguration>{{ cluster.security_configuration }}</SecurityConfiguration> | ||||||
|  |       {% endif %} | ||||||
|       <ServiceRole>{{ cluster.service_role }}</ServiceRole> |       <ServiceRole>{{ cluster.service_role }}</ServiceRole> | ||||||
|       <Status> |       <Status> | ||||||
|         <State>{{ cluster.state }}</State> |         <State>{{ cluster.state }}</State> | ||||||
| @ -1253,3 +1320,30 @@ REMOVE_AUTO_SCALING_POLICY = """<RemoveAutoScalingPolicyResponse xmlns="http://e | |||||||
|     <RequestId>c04a1042-5340-4c0a-a7b5-7779725ce4f7</RequestId> |     <RequestId>c04a1042-5340-4c0a-a7b5-7779725ce4f7</RequestId> | ||||||
|   </ResponseMetadata> |   </ResponseMetadata> | ||||||
| </RemoveAutoScalingPolicyResponse>""" | </RemoveAutoScalingPolicyResponse>""" | ||||||
|  | 
 | ||||||
|  | CREATE_SECURITY_CONFIGURATION_TEMPLATE = """<CreateSecurityConfigurationResponse xmlns="http://elasticmapreduce.amazonaws.com/doc/2009-03-31"> | ||||||
|  |   <CreateSecurityConfigurationResult> | ||||||
|  |     <Name>{{name}}</Name> | ||||||
|  |     <CreationDateTime>{{creation_date_time}}</CreationDateTime> | ||||||
|  |   </CreateSecurityConfigurationResult> | ||||||
|  |   <ResponseMetadata> | ||||||
|  |     <RequestId>2690d7eb-ed86-11dd-9877-6fad448a8419</RequestId> | ||||||
|  |   </ResponseMetadata> | ||||||
|  | </CreateSecurityConfigurationResponse>""" | ||||||
|  | 
 | ||||||
|  | DESCRIBE_SECURITY_CONFIGURATION_TEMPLATE = """<DescribeSecurityConfigurationResponse xmlns="http://elasticmapreduce.amazonaws.com/doc/2009-03-31"> | ||||||
|  |   <DescribeSecurityConfigurationResult> | ||||||
|  |     <Name>{{security_configuration['name']}}</Name> | ||||||
|  |     <SecurityConfiguration>{{security_configuration['security_configuration']}}</SecurityConfiguration> | ||||||
|  |     <CreationDateTime>{{security_configuration['creation_date_time']}}</CreationDateTime> | ||||||
|  |   </DescribeSecurityConfigurationResult> | ||||||
|  |   <ResponseMetadata> | ||||||
|  |     <RequestId>2690d7eb-ed86-11dd-9877-6fad448a8419</RequestId> | ||||||
|  |   </ResponseMetadata> | ||||||
|  | </DescribeSecurityConfigurationResponse>""" | ||||||
|  | 
 | ||||||
|  | DELETE_SECURITY_CONFIGURATION_TEMPLATE = """<DeleteSecurityConfigurationResponse xmlns="http://elasticmapreduce.amazonaws.com/doc/2009-03-31"> | ||||||
|  |   <ResponseMetadata> | ||||||
|  |     <RequestId>2690d7eb-ed86-11dd-9877-6fad448a8419</RequestId> | ||||||
|  |   </ResponseMetadata> | ||||||
|  | </DeleteSecurityConfigurationResponse>""" | ||||||
|  | |||||||
| @ -9,7 +9,7 @@ flask | |||||||
| flask-cors | flask-cors | ||||||
| boto>=2.45.0 | boto>=2.45.0 | ||||||
| boto3>=1.4.4 | boto3>=1.4.4 | ||||||
| botocore>=1.15.13 | botocore>=1.18.17 | ||||||
| six>=1.9 | six>=1.9 | ||||||
| prompt-toolkit==2.0.10 # 3.x is not available with python2 | prompt-toolkit==2.0.10 # 3.x is not available with python2 | ||||||
| click==6.7 | click==6.7 | ||||||
|  | |||||||
| @ -107,7 +107,15 @@ def test_describe_cluster(): | |||||||
|     args["Instances"]["EmrManagedSlaveSecurityGroup"] = "slave-security-group" |     args["Instances"]["EmrManagedSlaveSecurityGroup"] = "slave-security-group" | ||||||
|     args["Instances"]["KeepJobFlowAliveWhenNoSteps"] = False |     args["Instances"]["KeepJobFlowAliveWhenNoSteps"] = False | ||||||
|     args["Instances"]["ServiceAccessSecurityGroup"] = "service-access-security-group" |     args["Instances"]["ServiceAccessSecurityGroup"] = "service-access-security-group" | ||||||
|  |     args["KerberosAttributes"] = { | ||||||
|  |         "Realm": "MY-REALM.COM", | ||||||
|  |         "KdcAdminPassword": "SuperSecretPassword2", | ||||||
|  |         "CrossRealmTrustPrincipalPassword": "SuperSecretPassword3", | ||||||
|  |         "ADDomainJoinUser": "Bob", | ||||||
|  |         "ADDomainJoinPassword": "SuperSecretPassword4", | ||||||
|  |     } | ||||||
|     args["Tags"] = [{"Key": "tag1", "Value": "val1"}, {"Key": "tag2", "Value": "val2"}] |     args["Tags"] = [{"Key": "tag1", "Value": "val1"}, {"Key": "tag2", "Value": "val2"}] | ||||||
|  |     args["SecurityConfiguration"] = "my-security-configuration" | ||||||
| 
 | 
 | ||||||
|     cluster_id = client.run_job_flow(**args)["JobFlowId"] |     cluster_id = client.run_job_flow(**args)["JobFlowId"] | ||||||
| 
 | 
 | ||||||
| @ -145,6 +153,7 @@ def test_describe_cluster(): | |||||||
|         args["Instances"]["ServiceAccessSecurityGroup"] |         args["Instances"]["ServiceAccessSecurityGroup"] | ||||||
|     ) |     ) | ||||||
|     cl["Id"].should.equal(cluster_id) |     cl["Id"].should.equal(cluster_id) | ||||||
|  |     cl["KerberosAttributes"].should.equal(args["KerberosAttributes"]) | ||||||
|     cl["LogUri"].should.equal(args["LogUri"]) |     cl["LogUri"].should.equal(args["LogUri"]) | ||||||
|     cl["MasterPublicDnsName"].should.be.a(six.string_types) |     cl["MasterPublicDnsName"].should.be.a(six.string_types) | ||||||
|     cl["Name"].should.equal(args["Name"]) |     cl["Name"].should.equal(args["Name"]) | ||||||
| @ -152,7 +161,8 @@ def test_describe_cluster(): | |||||||
|     # cl['ReleaseLabel'].should.equal('emr-5.0.0') |     # cl['ReleaseLabel'].should.equal('emr-5.0.0') | ||||||
|     cl.shouldnt.have.key("RequestedAmiVersion") |     cl.shouldnt.have.key("RequestedAmiVersion") | ||||||
|     cl["RunningAmiVersion"].should.equal("1.0.0") |     cl["RunningAmiVersion"].should.equal("1.0.0") | ||||||
|     # cl['SecurityConfiguration'].should.be.a(six.string_types) |     cl["SecurityConfiguration"].should.be.a(six.string_types) | ||||||
|  |     cl["SecurityConfiguration"].should.equal(args["SecurityConfiguration"]) | ||||||
|     cl["ServiceRole"].should.equal(args["ServiceRole"]) |     cl["ServiceRole"].should.equal(args["ServiceRole"]) | ||||||
| 
 | 
 | ||||||
|     status = cl["Status"] |     status = cl["Status"] | ||||||
| @ -985,3 +995,53 @@ def test_tags(): | |||||||
|     client.remove_tags(ResourceId=cluster_id, TagKeys=[t["Key"] for t in input_tags]) |     client.remove_tags(ResourceId=cluster_id, TagKeys=[t["Key"] for t in input_tags]) | ||||||
|     resp = client.describe_cluster(ClusterId=cluster_id)["Cluster"] |     resp = client.describe_cluster(ClusterId=cluster_id)["Cluster"] | ||||||
|     resp["Tags"].should.equal([]) |     resp["Tags"].should.equal([]) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @mock_emr | ||||||
|  | def test_security_configurations(): | ||||||
|  | 
 | ||||||
|  |     client = boto3.client("emr", region_name="us-east-1") | ||||||
|  | 
 | ||||||
|  |     security_configuration_name = "MySecurityConfiguration" | ||||||
|  | 
 | ||||||
|  |     security_configuration = """ | ||||||
|  | { | ||||||
|  |   "EncryptionConfiguration": { | ||||||
|  |     "AtRestEncryptionConfiguration": { | ||||||
|  |       "S3EncryptionConfiguration": { | ||||||
|  |         "EncryptionMode": "SSE-S3" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     "EnableInTransitEncryption": false, | ||||||
|  |     "EnableAtRestEncryption": true | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |     """.strip() | ||||||
|  | 
 | ||||||
|  |     resp = client.create_security_configuration( | ||||||
|  |         Name=security_configuration_name, SecurityConfiguration=security_configuration | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  |     resp["Name"].should.equal(security_configuration_name) | ||||||
|  |     resp["CreationDateTime"].should.be.a("datetime.datetime") | ||||||
|  | 
 | ||||||
|  |     resp = client.describe_security_configuration(Name=security_configuration_name) | ||||||
|  |     resp["Name"].should.equal(security_configuration_name) | ||||||
|  |     resp["SecurityConfiguration"].should.equal(security_configuration) | ||||||
|  |     resp["CreationDateTime"].should.be.a("datetime.datetime") | ||||||
|  | 
 | ||||||
|  |     client.delete_security_configuration(Name=security_configuration_name) | ||||||
|  | 
 | ||||||
|  |     with pytest.raises(ClientError) as ex: | ||||||
|  |         client.describe_security_configuration(Name=security_configuration_name) | ||||||
|  |     ex.value.response["Error"]["Code"].should.equal("InvalidRequestException") | ||||||
|  |     ex.value.response["Error"]["Message"].should.match( | ||||||
|  |         r"Security configuration with name .* does not exist." | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  |     with pytest.raises(ClientError) as ex: | ||||||
|  |         client.delete_security_configuration(Name=security_configuration_name) | ||||||
|  |     ex.value.response["Error"]["Code"].should.equal("InvalidRequestException") | ||||||
|  |     ex.value.response["Error"]["Message"].should.match( | ||||||
|  |         r"Security configuration with name .* does not exist." | ||||||
|  |     ) | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user