Make IoT certificate ID generation deterministic and prevent duplicate certificates from being created (#3331)

* Make IoT certificate id generation deterministic

Fixes #3321

As per https://stackoverflow.com/questions/55847788/how-does-aws-iot-generate-a-certificate-id,
the IoT certificate ID is the SHA256 fingerprint of the
certificate. Since moto doesn't generate full certificates we will
instead use the SHA256 hash of the passed certificate pem.

* Don't allow duplicate IoT certificates to be created

Fixes #3320

When using boto3, trying to register a certificate that already
exists will throw a ResourceAlreadyExistsException. Moto should
follow the same pattern to allow testing error handling code in
this area.
This commit is contained in:
Ben Dennerley 2020-09-22 05:28:12 -04:00 committed by GitHub
commit 958e95cf5c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 58 additions and 2 deletions

View file

@ -503,6 +503,20 @@ def test_endpoints():
raise Exception("Should have raised error")
@mock_iot
def test_certificate_id_generation_deterministic():
# Creating the same certificate twice should result in the same certificate ID
client = boto3.client("iot", region_name="us-east-1")
cert1 = client.create_keys_and_certificate(setAsActive=False)
client.delete_certificate(certificateId=cert1["certificateId"])
cert2 = client.register_certificate(
certificatePem=cert1["certificatePem"], setAsActive=False
)
cert2.should.have.key("certificateId").which.should.equal(cert1["certificateId"])
client.delete_certificate(certificateId=cert2["certificateId"])
@mock_iot
def test_certs():
client = boto3.client("iot", region_name="us-east-1")
@ -584,6 +598,29 @@ def test_certs():
res.should.have.key("certificates")
@mock_iot
def test_create_certificate_validation():
# Test we can't create a cert that already exists
client = boto3.client("iot", region_name="us-east-1")
cert = client.create_keys_and_certificate(setAsActive=False)
with assert_raises(ClientError) as e:
client.register_certificate(
certificatePem=cert["certificatePem"], setAsActive=False
)
e.exception.response["Error"]["Message"].should.contain(
"The certificate is already provisioned or registered"
)
with assert_raises(ClientError) as e:
client.register_certificate_without_ca(
certificatePem=cert["certificatePem"], status="ACTIVE"
)
e.exception.response["Error"]["Message"].should.contain(
"The certificate is already provisioned or registered"
)
@mock_iot
def test_delete_policy_validation():
doc = """{