Skip to content
This repository has been archived by the owner on Nov 16, 2023. It is now read-only.

Commit

Permalink
Merge pull request #165 from Azure-Samples/drwill/dpsTpm
Browse files Browse the repository at this point in the history
Revamp DPS TPM sample
  • Loading branch information
David R. Williamson authored Dec 3, 2020
2 parents 5302f5c + 8d0a1fb commit 9246956
Show file tree
Hide file tree
Showing 12 changed files with 257 additions and 190 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ public async Task RunSampleAsync()
security,
transportHandler);

Console.WriteLine($"Initialized for registration Id {security.GetRegistrationID()}");
Console.WriteLine($"Initialized for registration Id {security.GetRegistrationID()}.");

Console.WriteLine("Registering with the device provisioning service... ");
Console.WriteLine("Registering with the device provisioning service...");
DeviceRegistrationResult result = await provClient.RegisterAsync();

Console.WriteLine($"Registration status: {result.Status}.");
Expand Down
52 changes: 52 additions & 0 deletions provisioning/Samples/device/TpmSample/Parameters.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using CommandLine;
using Microsoft.Azure.Devices.Client;

namespace Microsoft.Azure.Devices.Provisioning.Client.Samples
{
/// <summary>
/// Parameters for the application
/// </summary>
internal class Parameters
{
[Option(
'e',
"GetTpmEndorsementKey",
HelpText = "Gets the TPM endorsement key. Use this option by itself to get the EK needed to create a DPS individual enrollment.")]
public bool GetTpmEndorsementKey { get; set; }

[Option(
'u',
"UseTpmSimulator",
HelpText = "Runs the TPM simulator - useful when the local device does not have a TPM chip.")]
public bool UseTpmSimulator { get; set; }

[Option(
's',
"IdScope",
HelpText = "The Id Scope of the DPS instance. For normal runs, this is required.")]
public string IdScope { get; set; }

[Option(
'r',
"RegistrationId",
HelpText = "The registration Id from the individual enrollment. For normal runs, this is required.")]
public string RegistrationId { get; set; }

[Option(
'g',
"GlobalDeviceEndpoint",
Default = "global.azure-devices-provisioning.net",
HelpText = "The global endpoint for devices to connect to.")]
public string GlobalDeviceEndpoint { get; set; }

[Option(
't',
"TransportType",
Default = TransportType.Amqp,
HelpText = "The transport to use to communicate with the device provisioning instance. Possible values include Amqp, Amqp_WebSocket_Only, Amqp_Tcp_only, and Http1.")]
public TransportType TransportType { get; set; }
}
}
96 changes: 42 additions & 54 deletions provisioning/Samples/device/TpmSample/Program.cs
Original file line number Diff line number Diff line change
@@ -1,76 +1,64 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using Microsoft.Azure.Devices.Provisioning.Client;
using Microsoft.Azure.Devices.Provisioning.Client.Transport;
using CommandLine;
using Microsoft.Azure.Devices.Provisioning.Security;
using Microsoft.Azure.Devices.Provisioning.Security.Samples;
using Microsoft.Azure.Devices.Shared;
using System;
using System.Threading.Tasks;

namespace Microsoft.Azure.Devices.Provisioning.Client.Samples
{
/// <summary>
/// A sample to illustrate connecting a device to hub using the device provisioning service and a certificate.
/// </summary>
public static class Program
{
// The Provisioning Hub IDScope.

// For this sample either:
// - pass this value as a command-prompt argument
// - set the DPS_IDSCOPE environment variable
// - create a launchSettings.json (see launchSettings.json.template) containing the variable
private static string s_idScope = Environment.GetEnvironmentVariable("DPS_IDSCOPE");

private const string RegistrationId = "testtpmregistration1";
private const string GlobalDeviceEndpoint = "global.azure-devices-provisioning.net";

public static int Main(string[] args)
public static async Task<int> Main(string[] args)
{
if (string.IsNullOrWhiteSpace(s_idScope) && (args.Length > 0))
{
s_idScope = args[0];
}

if (string.IsNullOrWhiteSpace(s_idScope))
{
Console.WriteLine("ProvisioningDeviceClientTpm <IDScope>");
return 1;
}

// Remove if a real TPM is being used.
Console.WriteLine("Starting TPM simulator.");
SecurityProviderTpmSimulator.StartSimulatorProcess();

// Replace the following type with SecurityProviderTpmHsm() to use a real TPM2.0 device.
using (var security = new SecurityProviderTpmSimulator(RegistrationId))
// Parse application parameters
Parameters parameters = null;
ParserResult<Parameters> result = Parser.Default.ParseArguments<Parameters>(args)
.WithParsed(parsedParams =>
{
parameters = parsedParams;
})
.WithNotParsed(errors =>
{
Environment.Exit(1);
});

// Select one of the available transports:
// To optimize for size, reference only the protocols used by your application.
using (var transport = new ProvisioningTransportHandlerHttp())
// using (var transport = new ProvisioningTransportHandlerAmqp(TransportFallbackType.TcpOnly))
// using (var transport = new ProvisioningTransportHandlerAmqp(TransportFallbackType.WebSocketOnly))
// This sample provides a way to get the endorsement key (EK) required in creation of the individual enrollment
if (parameters.GetTpmEndorsementKey)
{
// Note that the TPM simulator will create an NVChip file containing the simulated TPM state.
Console.WriteLine("Extracting endorsement key.");
string base64EK = Convert.ToBase64String(security.GetEndorsementKey());
if (parameters.UseTpmSimulator)
{
Console.WriteLine("Starting TPM simulator...");
SecurityProviderTpmSimulator.StartSimulatorProcess();
}

Console.WriteLine(
"In your Azure Device Provisioning Service please go to 'Manage enrollments' and select " +
"'Individual Enrollments'. Select 'Add' then fill in the following:");
using var security = new SecurityProviderTpmHsm(null);
Console.WriteLine($"Your EK is {Convert.ToBase64String(security.GetEndorsementKey())}");

Console.WriteLine("\tMechanism: TPM");
Console.WriteLine($"\tRegistration ID: {RegistrationId}");
Console.WriteLine($"\tEndorsement key: {base64EK}");
Console.WriteLine("\tDevice ID: iothubtpmdevice1 (or any other valid DeviceID)");
Console.WriteLine();
Console.WriteLine("Press ENTER when ready.");
Console.ReadLine();
if (parameters.UseTpmSimulator)
{
SecurityProviderTpmSimulator.StopSimulatorProcess();
}

ProvisioningDeviceClient provClient =
ProvisioningDeviceClient.Create(GlobalDeviceEndpoint, s_idScope, security, transport);
return 0;
}

var sample = new ProvisioningDeviceClientSample(provClient, security);
sample.RunSampleAsync().GetAwaiter().GetResult();
// For a normal run of this sample, IdScope and RegistrationId are required
if (string.IsNullOrWhiteSpace(parameters.IdScope)
|| string.IsNullOrWhiteSpace(parameters.RegistrationId))
{
Console.WriteLine(CommandLine.Text.HelpText.AutoBuild(result, null, null));
Environment.Exit(1);
}

var sample = new ProvisioningDeviceClientSample(parameters);
await sample.RunSampleAsync();

return 0;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using Microsoft.Azure.Devices.Client;
using Microsoft.Azure.Devices.Provisioning.Client.Transport;
using Microsoft.Azure.Devices.Provisioning.Security;
using Microsoft.Azure.Devices.Provisioning.Security.Samples;
using Microsoft.Azure.Devices.Shared;
using System;
using System.Text;
using System.Threading.Tasks;

namespace Microsoft.Azure.Devices.Provisioning.Client.Samples
{
/// <summary>
/// Demonstrates how to register a device with the device provisioning service using a certificate, and then
/// use the registration information to authenticate to IoT Hub.
/// </summary>
internal class ProvisioningDeviceClientSample
{
private readonly Parameters _parameters;

public ProvisioningDeviceClientSample(Parameters parameters)
{
_parameters = parameters;
}

public async Task RunSampleAsync()
{
SecurityProviderTpm security = null;

try
{
if (_parameters.UseTpmSimulator)
{
Console.WriteLine("Starting TPM simulator...");
SecurityProviderTpmSimulator.StartSimulatorProcess();
security = new SecurityProviderTpmSimulator(_parameters.RegistrationId);
}
else
{
Console.WriteLine("Initializing security using the local TPM...");
security = new SecurityProviderTpmHsm(_parameters.RegistrationId);
}

Console.WriteLine($"Initializing the device provisioning client...");

using var transport = GetTransportHandler();
ProvisioningDeviceClient provClient = ProvisioningDeviceClient.Create(
_parameters.GlobalDeviceEndpoint,
_parameters.IdScope,
security,
transport);

Console.WriteLine($"Initialized for registration Id {security.GetRegistrationID()}.");

Console.WriteLine("Registering with the device provisioning service... ");
DeviceRegistrationResult result = await provClient.RegisterAsync();

Console.WriteLine($"Registration status: {result.Status}.");
if (result.Status != ProvisioningRegistrationStatusType.Assigned)
{
Console.WriteLine($"Registration status did not assign a hub, so exiting this sample.");
return;
}

Console.WriteLine($"Device {result.DeviceId} registered to {result.AssignedHub}.");

Console.WriteLine("Creating TPM authentication for IoT Hub...");
IAuthenticationMethod auth = new DeviceAuthenticationWithTpm(result.DeviceId, security);

Console.WriteLine($"Testing the provisioned device with IoT Hub...");
using DeviceClient iotClient = DeviceClient.Create(result.AssignedHub, auth, _parameters.TransportType);

Console.WriteLine("Sending a telemetry message...");
using var message = new Message(Encoding.UTF8.GetBytes("TestMessage"));
await iotClient.SendEventAsync(message);
}
finally
{
if (_parameters.UseTpmSimulator)
{
SecurityProviderTpmSimulator.StopSimulatorProcess();
}

security?.Dispose();
}

Console.WriteLine("Finished.");
}

private ProvisioningTransportHandler GetTransportHandler()
{
return _parameters.TransportType switch
{
TransportType.Amqp => new ProvisioningTransportHandlerAmqp(),
TransportType.Amqp_Tcp_Only => new ProvisioningTransportHandlerAmqp(TransportFallbackType.WebSocketOnly),
TransportType.Amqp_WebSocket_Only => new ProvisioningTransportHandlerAmqp(TransportFallbackType.TcpOnly),
TransportType.Http1 => new ProvisioningTransportHandlerHttp(),
TransportType.Mqtt => throw new NotSupportedException("MQTT is not supported for TPM"),
TransportType.Mqtt_Tcp_Only => throw new NotSupportedException("MQTT is not supported for TPM"),
TransportType.Mqtt_WebSocket_Only => throw new NotSupportedException("MQTT is not supported for TPM"),
_ => throw new NotSupportedException($"Unsupported transport type {_parameters.TransportType}"),
};
}
}
}
10 changes: 4 additions & 6 deletions provisioning/Samples/device/TpmSample/TpmSample.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,15 @@
</PropertyGroup>

<ItemGroup>
<Compile Include="..\Common\ProvisioningDeviceClientSample.cs" Link="ProvisioningDeviceClientSample.cs" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="CommandLineParser" Version="2.8.0" />
<PackageReference Include="Microsoft.Azure.Devices.Client" Version="1.33.1" />
<PackageReference Include="Microsoft.Azure.Devices.Provisioning.Client" Version="1.*" />
<PackageReference Include="Microsoft.Azure.Devices.Provisioning.Security.Tpm" Version="1.*" />
<PackageReference Include="Microsoft.Azure.Devices.Provisioning.Security.Tpm" Version="1.12.2" />

<!-- Note: Applications should not need to import both protocols. This was done to simplify protocol selection within the sample.-->
<!-- Note: Applications should not need to import all 3 protocols. This was done to simplify protocol selection within the sample.-->
<PackageReference Include="Microsoft.Azure.Devices.Provisioning.Transport.Amqp" Version="1.13.3" />
<PackageReference Include="Microsoft.Azure.Devices.Provisioning.Transport.Http" Version="1.12.2" />
<PackageReference Include="Microsoft.Azure.Devices.Provisioning.Transport.Mqtt" Version="1.13.2" />
</ItemGroup>

<ItemGroup>
Expand Down
Loading

0 comments on commit 9246956

Please sign in to comment.