/// <summary> /// Provisions a device to a starting hub, tries to open a connection, send telemetry, /// and (if supported by the protocol) send a twin update. Then, this method updates the enrollment /// to provision the device to a different hub. Based on the provided reprovisioning settings, this /// method then checks that the device was/was not reprovisioned as expected, and that the device /// did/did not migrate twin data as expected. /// </summary> public async Task ProvisioningDeviceClient_ReprovisioningFlow( Client.TransportType transportProtocol, AttestationType attestationType, EnrollmentType?enrollmentType, bool setCustomProxy, ReprovisionPolicy reprovisionPolicy, AllocationPolicy allocationPolicy, CustomAllocationDefinition customAllocationDefinition, ICollection <string> iotHubsToStartAt, ICollection <string> iotHubsToReprovisionTo, string proxyServerAddress = null) { ProvisioningServiceClient provisioningServiceClient = CreateProvisioningService(s_proxyServerAddress); string groupId = _devicePrefix + AttestationTypeToString(attestationType) + "-" + Guid.NewGuid(); bool twinOperationsAllowed = transportProtocol != Client.TransportType.Http1; using ProvisioningTransportHandler transport = ProvisioningE2ETests.CreateTransportHandlerFromName(transportProtocol); using SecurityProvider security = await CreateSecurityProviderFromName( attestationType, enrollmentType, groupId, reprovisionPolicy, allocationPolicy, customAllocationDefinition, iotHubsToStartAt) .ConfigureAwait(false); //Check basic provisioning if (ProvisioningE2ETests.ImplementsWebProxy(transportProtocol) && setCustomProxy) { transport.Proxy = (proxyServerAddress != null) ? new WebProxy(s_proxyServerAddress) : null; } ProvisioningDeviceClient provClient = ProvisioningDeviceClient.Create( s_globalDeviceEndpoint, Configuration.Provisioning.IdScope, security, transport); using var cts = new CancellationTokenSource(PassingTimeoutMiliseconds); DeviceRegistrationResult result = await provClient.RegisterAsync(cts.Token).ConfigureAwait(false); ValidateDeviceRegistrationResult(result); Client.IAuthenticationMethod auth = CreateAuthenticationMethodFromSecurityProvider(security, result.DeviceId); await ConfirmRegisteredDeviceWorks(result, auth, transportProtocol, twinOperationsAllowed).ConfigureAwait(false); //Check reprovisioning await UpdateEnrollmentToForceReprovision(enrollmentType, provisioningServiceClient, iotHubsToReprovisionTo, security, groupId).ConfigureAwait(false); result = await provClient.RegisterAsync(cts.Token).ConfigureAwait(false); ConfirmDeviceInExpectedHub(result, reprovisionPolicy, iotHubsToStartAt, iotHubsToReprovisionTo, allocationPolicy); await ConfirmDeviceWorksAfterReprovisioning(result, auth, transportProtocol, reprovisionPolicy, twinOperationsAllowed).ConfigureAwait(false); if (attestationType != AttestationType.x509) //x509 enrollments are hardcoded, should never be deleted { await ProvisioningE2ETests.DeleteCreatedEnrollment(enrollmentType, provisioningServiceClient, security, groupId).ConfigureAwait(false); } }
private async Task <SecurityProvider> CreateSecurityProviderFromName(AttestationType attestationType, EnrollmentType?enrollmentType, string groupId, ReprovisionPolicy reprovisionPolicy, AllocationPolicy allocationPolicy, CustomAllocationDefinition customAllocationDefinition, ICollection <string> iothubs, DeviceCapabilities capabilities = null) { _verboseLog.WriteLine($"{nameof(CreateSecurityProviderFromName)}({attestationType})"); var provisioningServiceClient = ProvisioningServiceClient.CreateFromConnectionString(Configuration.Provisioning.ConnectionString); switch (attestationType) { case AttestationType.Tpm: string registrationId = AttestationTypeToString(attestationType) + "-registration-id-" + Guid.NewGuid(); var tpmSim = new SecurityProviderTpmSimulator(registrationId); string base64Ek = Convert.ToBase64String(tpmSim.GetEndorsementKey()); var provisioningService = ProvisioningServiceClient.CreateFromConnectionString(Configuration.Provisioning.ConnectionString); _log.WriteLine($"Getting enrollment: RegistrationID = {registrationId}"); IndividualEnrollment individualEnrollment = new IndividualEnrollment(registrationId, new TpmAttestation(base64Ek)) { AllocationPolicy = allocationPolicy, ReprovisionPolicy = reprovisionPolicy, IotHubs = iothubs, CustomAllocationDefinition = customAllocationDefinition, Capabilities = capabilities }; IndividualEnrollment enrollment = await provisioningService.CreateOrUpdateIndividualEnrollmentAsync(individualEnrollment).ConfigureAwait(false); var attestation = new TpmAttestation(base64Ek); enrollment.Attestation = attestation; _log.WriteLine($"Updating enrollment: RegistrationID = {registrationId} EK = '{base64Ek}'"); await provisioningService.CreateOrUpdateIndividualEnrollmentAsync(enrollment).ConfigureAwait(false); return(tpmSim); case AttestationType.x509: X509Certificate2 certificate = null; X509Certificate2Collection collection = null; switch (enrollmentType) { case EnrollmentType.Individual: certificate = Configuration.Provisioning.GetIndividualEnrollmentCertificate(); break; case EnrollmentType.Group: certificate = Configuration.Provisioning.GetGroupEnrollmentCertificate(); collection = Configuration.Provisioning.GetGroupEnrollmentChain(); break; default: throw new NotSupportedException($"Unknown X509 type: '{enrollmentType}'"); } return(new SecurityProviderX509Certificate(certificate, collection)); case AttestationType.SymmetricKey: switch (enrollmentType) { case EnrollmentType.Group: EnrollmentGroup symmetricKeyEnrollmentGroup = await CreateEnrollmentGroup(provisioningServiceClient, AttestationType.SymmetricKey, groupId, reprovisionPolicy, allocationPolicy, customAllocationDefinition, iothubs, capabilities).ConfigureAwait(false); Assert.IsTrue(symmetricKeyEnrollmentGroup.Attestation is SymmetricKeyAttestation); SymmetricKeyAttestation symmetricKeyAttestation = (SymmetricKeyAttestation)symmetricKeyEnrollmentGroup.Attestation; string registrationIdSymmetricKey = IdPrefix + Guid.NewGuid(); string primaryKeyEnrollmentGroup = symmetricKeyAttestation.PrimaryKey; string secondaryKeyEnrollmentGroup = symmetricKeyAttestation.SecondaryKey; string primaryKeyIndividual = ProvisioningE2ETests.ComputeDerivedSymmetricKey(Convert.FromBase64String(primaryKeyEnrollmentGroup), registrationIdSymmetricKey); string secondaryKeyIndividual = ProvisioningE2ETests.ComputeDerivedSymmetricKey(Convert.FromBase64String(secondaryKeyEnrollmentGroup), registrationIdSymmetricKey); return(new SecurityProviderSymmetricKey(registrationIdSymmetricKey, primaryKeyIndividual, secondaryKeyIndividual)); case EnrollmentType.Individual: IndividualEnrollment symmetricKeyEnrollment = await CreateIndividualEnrollment(provisioningServiceClient, AttestationType.SymmetricKey, reprovisionPolicy, allocationPolicy, customAllocationDefinition, iothubs, capabilities).ConfigureAwait(false); Assert.IsTrue(symmetricKeyEnrollment.Attestation is SymmetricKeyAttestation); symmetricKeyAttestation = (SymmetricKeyAttestation)symmetricKeyEnrollment.Attestation; registrationIdSymmetricKey = symmetricKeyEnrollment.RegistrationId; string primaryKey = symmetricKeyAttestation.PrimaryKey; string secondaryKey = symmetricKeyAttestation.SecondaryKey; return(new SecurityProviderSymmetricKey(registrationIdSymmetricKey, primaryKey, secondaryKey)); default: throw new NotSupportedException("Unrecognized enrollment type"); } default: throw new NotSupportedException("Unrecognized attestation type"); } throw new NotSupportedException($"Unknown security type: '{attestationType}'."); }