|
1 | 1 | // Copyright (c) Microsoft. All rights reserved. |
2 | 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. |
3 | 3 |
|
4 | | -using Microsoft.Azure.Devices.Provisioning.Client; |
| 4 | +using CommandLine; |
5 | 5 | using Microsoft.Azure.Devices.Provisioning.Client.Samples; |
6 | | -using Microsoft.Azure.Devices.Provisioning.Client.Transport; |
7 | | -using Microsoft.Azure.Devices.Shared; |
8 | 6 | using System; |
9 | | -using System.Security.Cryptography; |
10 | | -using System.Text; |
| 7 | +using System.Threading.Tasks; |
11 | 8 |
|
12 | 9 | namespace SymmetricKeySample |
13 | 10 | { |
14 | | - class Program |
| 11 | + /// <summary> |
| 12 | + /// A sample to illustrate connecting a device to hub using the device provisioning service. |
| 13 | + /// </summary> |
| 14 | + internal class Program |
15 | 15 | { |
16 | | - // The Provisioning Hub IDScope. |
17 | | - |
18 | | - // For this sample either: |
19 | | - // - pass this value as a command-prompt argument |
20 | | - // - set the DPS_IDSCOPE environment variable |
21 | | - // - create a launchSettings.json (see launchSettings.json.template) containing the variable |
22 | | - private static string s_idScope = Environment.GetEnvironmentVariable("DPS_IDSCOPE"); |
23 | | - |
24 | | - // In your Device Provisioning Service please go to "Manage enrollments" and select "Individual Enrollments". |
25 | | - // Select "Add individual enrollment" then fill in the following: |
26 | | - // Mechanism: Symmetric Key |
27 | | - // Auto-generate keys should be checked |
28 | | - // DeviceID: iothubSymmetricKeydevice1 |
29 | | - |
30 | | - // Symmetric Keys may also be used for enrollment groups. |
31 | | - // In your Device Provisioning Service please go to "Manage enrollments" and select "Enrollment Groups". |
32 | | - // Select "Add enrollment group" then fill in the following: |
33 | | - // Group name: <your group name> |
34 | | - // Attestation Type: Symmetric Key |
35 | | - // Auto-generate keys should be checked |
36 | | - // You may also change other enrollment group parameters according to your needs |
37 | | - |
38 | | - private const string GlobalDeviceEndpoint = "global.azure-devices-provisioning.net"; |
39 | | - |
40 | | - //These are the two keys that belong to your enrollment group. |
41 | | - // Leave them blank if you want to try this sample for an individual enrollment instead |
42 | | - private const string enrollmentGroupPrimaryKey = ""; |
43 | | - private const string enrollmentGroupSecondaryKey = ""; |
44 | | - |
45 | | - //registration id for enrollment groups can be chosen arbitrarily and do not require any portal setup. |
46 | | - //The chosen value will become the provisioned device's device id. |
47 | | - // |
48 | | - //registration id for individual enrollments must be retrieved from the portal and will be unrelated to the provioned |
49 | | - //device's device id |
50 | | - // |
51 | | - //This field is mandatory to provide for this sample |
52 | | - private static string registrationId = ""; |
53 | | - |
54 | | - //These are the two keys that belong to your individual enrollment. |
55 | | - // Leave them blank if you want to try this sample for an individual enrollment instead |
56 | | - private const string individualEnrollmentPrimaryKey = ""; |
57 | | - private const string individualEnrollmentSecondaryKey = ""; |
58 | | - |
59 | | - public static int Main(string[] args) |
| 16 | + public static async Task<int> Main(string[] args) |
60 | 17 | { |
61 | | - if (string.IsNullOrWhiteSpace(s_idScope) && (args.Length > 0)) |
62 | | - { |
63 | | - s_idScope = args[0]; |
64 | | - } |
| 18 | + // Parse application parameters |
| 19 | + Parameters parameters = null; |
| 20 | + ParserResult<Parameters> result = Parser.Default.ParseArguments<Parameters>(args) |
| 21 | + .WithParsed(parsedParams => |
| 22 | + { |
| 23 | + parameters = parsedParams; |
| 24 | + }) |
| 25 | + .WithNotParsed(errors => |
| 26 | + { |
| 27 | + Environment.Exit(1); |
| 28 | + }); |
| 29 | + |
| 30 | + var sample = new ProvisioningDeviceClientSample(parameters); |
| 31 | + await sample.RunSampleAsync(); |
| 32 | + |
| 33 | + Console.WriteLine("Enter any key to exit."); |
| 34 | + Console.ReadKey(); |
65 | 35 |
|
66 | | - if (string.IsNullOrWhiteSpace(s_idScope)) |
67 | | - { |
68 | | - Console.WriteLine("ProvisioningDeviceClientSymmetricKey <IDScope>"); |
69 | | - return 1; |
70 | | - } |
71 | | - |
72 | | - string primaryKey = ""; |
73 | | - string secondaryKey = ""; |
74 | | - if (!String.IsNullOrEmpty(registrationId) && !String.IsNullOrEmpty(enrollmentGroupPrimaryKey) && !String.IsNullOrEmpty(enrollmentGroupSecondaryKey)) |
75 | | - { |
76 | | - //Group enrollment flow, the primary and secondary keys are derived from the enrollment group keys and from the desired registration id |
77 | | - primaryKey = ComputeDerivedSymmetricKey(Convert.FromBase64String(enrollmentGroupPrimaryKey), registrationId); |
78 | | - secondaryKey = ComputeDerivedSymmetricKey(Convert.FromBase64String(enrollmentGroupSecondaryKey), registrationId); |
79 | | - } |
80 | | - else if (!String.IsNullOrEmpty(registrationId) && !String.IsNullOrEmpty(individualEnrollmentPrimaryKey) && !String.IsNullOrEmpty(individualEnrollmentSecondaryKey)) |
81 | | - { |
82 | | - //Individual enrollment flow, the primary and secondary keys are the same as the individual enrollment keys |
83 | | - primaryKey = individualEnrollmentPrimaryKey; |
84 | | - secondaryKey = individualEnrollmentSecondaryKey; |
85 | | - } |
86 | | - else |
87 | | - { |
88 | | - Console.WriteLine("Invalid configuration provided, must provide group enrollment keys or individual enrollment keys"); |
89 | | - return -1; |
90 | | - } |
91 | | - |
92 | | - using (var security = new SecurityProviderSymmetricKey(registrationId, primaryKey, secondaryKey)) |
93 | | - |
94 | | - // Select one of the available transports: |
95 | | - // To optimize for size, reference only the protocols used by your application. |
96 | | - using (var transport = new ProvisioningTransportHandlerAmqp(TransportFallbackType.TcpOnly)) |
97 | | - // using (var transport = new ProvisioningTransportHandlerHttp()) |
98 | | - // using (var transport = new ProvisioningTransportHandlerMqtt(TransportFallbackType.TcpOnly)) |
99 | | - // using (var transport = new ProvisioningTransportHandlerMqtt(TransportFallbackType.WebSocketOnly)) |
100 | | - { |
101 | | - ProvisioningDeviceClient provClient = |
102 | | - ProvisioningDeviceClient.Create(GlobalDeviceEndpoint, s_idScope, security, transport); |
103 | | - |
104 | | - var sample = new ProvisioningDeviceClientSample(provClient, security); |
105 | | - sample.RunSampleAsync().GetAwaiter().GetResult(); |
106 | | - } |
107 | | - Console.WriteLine("Enter any key to exit"); |
108 | | - Console.ReadLine(); |
109 | 36 | return 0; |
110 | 37 | } |
111 | | - |
112 | | - /// <summary> |
113 | | - /// Generate the derived symmetric key for the provisioned device from the enrollment group symmetric key used in attestation |
114 | | - /// </summary> |
115 | | - /// <param name="masterKey">Symmetric key enrollment group primary/secondary key value</param> |
116 | | - /// <param name="registrationId">the registration id to create</param> |
117 | | - /// <returns>the primary/secondary key for the member of the enrollment group</returns> |
118 | | - public static string ComputeDerivedSymmetricKey(byte[] masterKey, string registrationId) |
119 | | - { |
120 | | - using (var hmac = new HMACSHA256(masterKey)) |
121 | | - { |
122 | | - return Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(registrationId))); |
123 | | - } |
124 | | - } |
125 | 38 | } |
126 | 39 | } |
0 commit comments