From 8ccc00a39bceb0c69026f71aa9b31f5ea7ea965b Mon Sep 17 00:00:00 2001 From: ngastelum-ms <109701188+ngastelum-ms@users.noreply.github.com> Date: Tue, 22 Nov 2022 14:54:02 -0800 Subject: [PATCH] Delete provisioning/device/samples/Getting Started directory (#2986) --- .../ComputeDerivedKeySample.cs | 54 ------- .../ComputeDerivedSymmetricKeySample.csproj | 13 -- .../Parameters.cs | 27 ---- .../Program.cs | 29 ---- .../X509Sample/GenerateTestCertificate.ps1 | 48 ------ .../Getting Started/X509Sample/Parameters.cs | 115 -------------- .../Getting Started/X509Sample/Program.cs | 35 ----- .../ProvisioningDeviceClientSample.cs | 145 ------------------ .../X509Sample/X509Sample.csproj | 32 ---- .../Getting Started/X509Sample/readme.md | 61 -------- 10 files changed, 559 deletions(-) delete mode 100644 provisioning/device/samples/Getting Started/ComputeDerivedSymmetricKeySample/ComputeDerivedKeySample.cs delete mode 100644 provisioning/device/samples/Getting Started/ComputeDerivedSymmetricKeySample/ComputeDerivedSymmetricKeySample.csproj delete mode 100644 provisioning/device/samples/Getting Started/ComputeDerivedSymmetricKeySample/Parameters.cs delete mode 100644 provisioning/device/samples/Getting Started/ComputeDerivedSymmetricKeySample/Program.cs delete mode 100644 provisioning/device/samples/Getting Started/X509Sample/GenerateTestCertificate.ps1 delete mode 100644 provisioning/device/samples/Getting Started/X509Sample/Parameters.cs delete mode 100644 provisioning/device/samples/Getting Started/X509Sample/Program.cs delete mode 100644 provisioning/device/samples/Getting Started/X509Sample/ProvisioningDeviceClientSample.cs delete mode 100644 provisioning/device/samples/Getting Started/X509Sample/X509Sample.csproj delete mode 100644 provisioning/device/samples/Getting Started/X509Sample/readme.md diff --git a/provisioning/device/samples/Getting Started/ComputeDerivedSymmetricKeySample/ComputeDerivedKeySample.cs b/provisioning/device/samples/Getting Started/ComputeDerivedSymmetricKeySample/ComputeDerivedKeySample.cs deleted file mode 100644 index 5bff62f7dd..0000000000 --- a/provisioning/device/samples/Getting Started/ComputeDerivedSymmetricKeySample/ComputeDerivedKeySample.cs +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System; -using System.Security.Cryptography; -using System.Text; - -namespace Microsoft.Azure.Devices.Provisioning.Client.Samples -{ - /// - /// This sample demonstrates how to derive the symmetric key for a particular device enrollment within an enrollment - /// group. Best security practices dictate that the enrollment group level symmetric key should never be saved to a - /// particular device, so this code is deliberately separate from the SymmetricKeySample in this same directory. - /// Users are advised to run this code to generate the derived symmetric key once, and to save - /// the derived key to the device. Users are not advised to derive the device symmetric key from the enrollment group - /// level key within each device as that is unsecure. - /// - internal class ComputeDerivedKeySample - { - private readonly Parameters _parameters; - - public ComputeDerivedKeySample(Parameters parameters) - { - _parameters = parameters; - } - - public void RunSample() - { - string derivedKey = ComputeDerivedSymmetricKey(_parameters.PrimaryKey, _parameters.RegistrationId); - - Console.WriteLine($"Your derived device key is:'{derivedKey}'"); - } - - /// - /// Compute a symmetric key for the provisioned device from the enrollment group symmetric key used in attestation. - /// - /// Enrollment group symmetric key. - /// The registration Id of the key to create. - /// The key for the specified device Id registration in the enrollment group. - /// - /// https://docs.microsoft.com/azure/iot-edge/how-to-auto-provision-symmetric-keys#derive-a-device-key - /// - private static string ComputeDerivedSymmetricKey(string enrollmentKey, string registrationId) - { - if (string.IsNullOrWhiteSpace(enrollmentKey)) - { - return enrollmentKey; - } - - using var hmac = new HMACSHA256(Convert.FromBase64String(enrollmentKey)); - return Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(registrationId))); - } - } -} diff --git a/provisioning/device/samples/Getting Started/ComputeDerivedSymmetricKeySample/ComputeDerivedSymmetricKeySample.csproj b/provisioning/device/samples/Getting Started/ComputeDerivedSymmetricKeySample/ComputeDerivedSymmetricKeySample.csproj deleted file mode 100644 index 1fe6d00f34..0000000000 --- a/provisioning/device/samples/Getting Started/ComputeDerivedSymmetricKeySample/ComputeDerivedSymmetricKeySample.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - Exe - net6.0 - 9.0 - Microsoft.Azure.Devices.Provisioning.Client.Samples - - - - - - diff --git a/provisioning/device/samples/Getting Started/ComputeDerivedSymmetricKeySample/Parameters.cs b/provisioning/device/samples/Getting Started/ComputeDerivedSymmetricKeySample/Parameters.cs deleted file mode 100644 index e7ba947dfb..0000000000 --- a/provisioning/device/samples/Getting Started/ComputeDerivedSymmetricKeySample/Parameters.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using CommandLine; - -namespace Microsoft.Azure.Devices.Provisioning.Client.Samples -{ - /// - /// Parameters for the application - /// - internal class Parameters - { - [Option( - 'r', - "RegistrationId", - Required = true, - HelpText = "The desired registration Id of the device that will use this derived key.")] - public string RegistrationId { get; set; } - - [Option( - 'p', - "PrimaryKey", - Required = true, - HelpText = "The primary key of the group enrollment.")] - public string PrimaryKey { get; set; } - } -} diff --git a/provisioning/device/samples/Getting Started/ComputeDerivedSymmetricKeySample/Program.cs b/provisioning/device/samples/Getting Started/ComputeDerivedSymmetricKeySample/Program.cs deleted file mode 100644 index 431e6628e4..0000000000 --- a/provisioning/device/samples/Getting Started/ComputeDerivedSymmetricKeySample/Program.cs +++ /dev/null @@ -1,29 +0,0 @@ -using CommandLine; -using Microsoft.Azure.Devices.Provisioning.Client.Samples; -using System; - -namespace ComputeDerivedSymmetricKeySample -{ - internal class Program - { - private static int Main(string[] args) - { - // Parse application parameters - Parameters parameters = null; - ParserResult result = Parser.Default.ParseArguments(args) - .WithParsed(parsedParams => - { - parameters = parsedParams; - }) - .WithNotParsed(errors => - { - Environment.Exit(1); - }); - - var sample = new ComputeDerivedKeySample(parameters); - sample.RunSample(); - - return 0; - } - } -} diff --git a/provisioning/device/samples/Getting Started/X509Sample/GenerateTestCertificate.ps1 b/provisioning/device/samples/Getting Started/X509Sample/GenerateTestCertificate.ps1 deleted file mode 100644 index 0383d2e53c..0000000000 --- a/provisioning/device/samples/Getting Started/X509Sample/GenerateTestCertificate.ps1 +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright (c) Microsoft. All rights reserved. -# Licensed under the MIT license. See LICENSE file in the project root for full license information. - -<# - -.SYNOPSIS -Self-signed device certificate generator. - -.DESCRIPTION -Generates an X509 test certificate with the specified Common Name (CN). - -.\GenerateTestCertificate.ps1 - -.EXAMPLE -.\GenerateTestCertificate.ps1 testdevice1 - -.NOTES - - -.LINK -https://github.com/azure/azure-iot-sdk-csharp - -#> - -Param( - $deviceName = "iothubx509device1", - $certificateValidityInYears = 1 -) - -$cert = New-SelfSignedCertificate ` - -Type Custom ` - -Subject "CN=$deviceName, O=TEST, C=US" ` - -KeySpec Signature ` - -KeyExportPolicy Exportable ` - -HashAlgorithm sha256 ` - -KeyLength 2048 ` - -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.2") ` - -CertStoreLocation "Cert:\CurrentUser\My" ` - -NotAfter (Get-Date).AddYears($certificateValidityInYears) - -Write-Host "Generated the certificate:" -Write-Host $cert - -Write-Host "Enter the PFX password:" -$password = Read-Host -AsSecureString - -$cert | Export-PfxCertificate -FilePath certificate.pfx -Password $password -Set-Content -Path certificate.cer -Value ([Convert]::ToBase64String($cert.RawData)) -Encoding Ascii diff --git a/provisioning/device/samples/Getting Started/X509Sample/Parameters.cs b/provisioning/device/samples/Getting Started/X509Sample/Parameters.cs deleted file mode 100644 index d55e79f269..0000000000 --- a/provisioning/device/samples/Getting Started/X509Sample/Parameters.cs +++ /dev/null @@ -1,115 +0,0 @@ -// 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; -using System; -using System.IO; -using System.Reflection; - -namespace Microsoft.Azure.Devices.Provisioning.Client.Samples -{ - public enum Transport - { - Mqtt, - Amqp, - }; - - /// - /// Parameters for the application - /// - internal class Parameters - { - [Option( - 's', - "IdScope", - Required = true, - HelpText = "The Id Scope of the DPS instance")] - public string IdScope { get; set; } - - [Option( - 'n', - "CertificateName", - Default = "certificate.pfx", - HelpText = "The PFX certificate to load for device provisioning authentication.")] - public string CertificateName { get; set; } - - [Option( - 'p', - "CertificatePassword", - HelpText = "The password of the PFX certificate file. If not specified, the program will prompt at run time.")] - public string CertificatePassword { 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( - "Transport", - Default = Transport.Mqtt, - HelpText = "The transport to use for the connection.")] - public Transport Transport { get; set; } - - [Option( - "TransportProtocol", - Default = ProvisioningClientTransportProtocol.Tcp, - HelpText = "The transport to use to communicate with the device provisioning instance.")] - public ProvisioningClientTransportProtocol TransportProtocol { get; set; } - - internal string GetCertificatePath() - { - if (string.IsNullOrWhiteSpace(CertificateName)) - { - throw new InvalidOperationException("The certificate name has not been set."); - } - - string codeBase = Assembly.GetExecutingAssembly().Location; - string workingDirectory = Path.GetDirectoryName(codeBase); - - // Ascend the directory looking for one that has a certificate with the specified name, - // because the sample exe is likely in a build output folder ~3 levels below in - // the project folder. - while (!string.IsNullOrWhiteSpace(workingDirectory)) - { - string certificatePath = Path.Combine(workingDirectory, CertificateName); - if (File.Exists(certificatePath)) - { - return certificatePath; - } - - workingDirectory = Directory.GetParent(workingDirectory)?.FullName; - } - - // Once we get to the root, the call to parent will return null - // so that is our failure condition. - throw new InvalidOperationException($"Could not find the certificate file {CertificateName} in the sample execution folder or any parent folder."); - } - - internal ProvisioningClientOptions GetClientOptions() - { - return Transport switch - { - Transport.Mqtt => new ProvisioningClientOptions(new ProvisioningClientMqttSettings(TransportProtocol)), - Transport.Amqp => new ProvisioningClientOptions(new ProvisioningClientAmqpSettings(TransportProtocol)), - _ => throw new NotSupportedException($"Unsupported transport type {Transport}/{TransportProtocol}"), - }; - } - - internal IotHubClientTransportSettings GetHubTransportSettings() - { - IotHubClientTransportProtocol protocol = TransportProtocol == ProvisioningClientTransportProtocol.Tcp - ? IotHubClientTransportProtocol.Tcp - : IotHubClientTransportProtocol.WebSocket; - - return Transport switch - { - Transport.Mqtt => new IotHubClientMqttSettings(protocol), - Transport.Amqp => new IotHubClientAmqpSettings(protocol), - _ => throw new NotSupportedException($"Unsupported transport type {Transport}/{TransportProtocol}"), - }; - } - } -} diff --git a/provisioning/device/samples/Getting Started/X509Sample/Program.cs b/provisioning/device/samples/Getting Started/X509Sample/Program.cs deleted file mode 100644 index ea02c5b9f0..0000000000 --- a/provisioning/device/samples/Getting Started/X509Sample/Program.cs +++ /dev/null @@ -1,35 +0,0 @@ -// 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 System; -using System.Threading.Tasks; - -namespace Microsoft.Azure.Devices.Provisioning.Client.Samples -{ - /// - /// A sample to illustrate connecting a device to hub using the device provisioning service and a certificate. - /// - internal class Program - { - public static async Task Main(string[] args) - { - // Parse application parameters - Parameters parameters = null; - ParserResult result = Parser.Default.ParseArguments(args) - .WithParsed(parsedParams => - { - parameters = parsedParams; - }) - .WithNotParsed(errors => - { - Environment.Exit(1); - }); - - var sample = new ProvisioningDeviceClientSample(parameters); - await sample.RunSampleAsync(); - - return 0; - } - } -} diff --git a/provisioning/device/samples/Getting Started/X509Sample/ProvisioningDeviceClientSample.cs b/provisioning/device/samples/Getting Started/X509Sample/ProvisioningDeviceClientSample.cs deleted file mode 100644 index 69b0454148..0000000000 --- a/provisioning/device/samples/Getting Started/X509Sample/ProvisioningDeviceClientSample.cs +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System; -using System.IO; -using System.Security.Cryptography.X509Certificates; -using System.Text; -using System.Threading.Tasks; -using Microsoft.Azure.Devices.Client; - -namespace Microsoft.Azure.Devices.Provisioning.Client.Samples -{ - /// - /// 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. - /// - internal class ProvisioningDeviceClientSample - { - private readonly Parameters _parameters; - - public ProvisioningDeviceClientSample(Parameters parameters) - { - _parameters = parameters; - } - - public async Task RunSampleAsync() - { - Console.WriteLine($"Loading the certificate..."); - using X509Certificate2 certificate = LoadProvisioningCertificate(); - var security = new AuthenticationProviderX509(certificate); - - Console.WriteLine($"Initializing the device provisioning client..."); - - ProvisioningClientOptions clientOptions = _parameters.GetClientOptions(); - var provClient = new ProvisioningDeviceClient( - _parameters.GlobalDeviceEndpoint, - _parameters.IdScope, - security, - clientOptions); - - 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 X509 authentication for IoT Hub..."); - var auth = new ClientAuthenticationWithX509Certificate( - certificate, - result.DeviceId); - - Console.WriteLine($"Testing the provisioned device with IoT Hub..."); - IotHubClientTransportSettings transportSettings = _parameters.GetHubTransportSettings(); - var hubOptions = new IotHubClientOptions(transportSettings); - await using var iotClient = new IotHubDeviceClient(result.AssignedHub, auth, hubOptions); - await iotClient.OpenAsync(); - - Console.WriteLine("Sending a telemetry message..."); - var message = new TelemetryMessage("TestMessage"); - await iotClient.SendTelemetryAsync(message); - - await iotClient.CloseAsync(); - Console.WriteLine("Finished."); - } - - private X509Certificate2 LoadProvisioningCertificate() - { - ReadCertificatePassword(); - - var certificateCollection = new X509Certificate2Collection(); - certificateCollection.Import( - _parameters.GetCertificatePath(), - _parameters.CertificatePassword, - X509KeyStorageFlags.UserKeySet); - - X509Certificate2 certificate = null; - - foreach (X509Certificate2 element in certificateCollection) - { - Console.WriteLine($"Found certificate: {element?.Thumbprint} {element?.Subject}; PrivateKey: {element?.HasPrivateKey}"); - if (certificate == null && element.HasPrivateKey) - { - certificate = element; - } - else - { - element.Dispose(); - } - } - - if (certificate == null) - { - throw new FileNotFoundException($"{_parameters.CertificateName} did not contain any certificate with a private key."); - } - - Console.WriteLine($"Using certificate {certificate.Thumbprint} {certificate.Subject}"); - - return certificate; - } - - private void ReadCertificatePassword() - { - if (!string.IsNullOrWhiteSpace(_parameters.CertificatePassword)) - { - return; - } - - var password = new StringBuilder(); - Console.WriteLine($"Enter the PFX password for {_parameters.CertificateName}:"); - - while (true) - { - ConsoleKeyInfo key = Console.ReadKey(true); - if (key.Key == ConsoleKey.Backspace) - { - if (password.Length > 0) - { - password.Remove(password.Length - 1, 1); - Console.Write("\b \b"); - } - } - else if (key.Key == ConsoleKey.Enter) - { - Console.WriteLine(); - break; - } - else - { - Console.Write('*'); - password.Append(key.KeyChar); - } - } - - _parameters.CertificatePassword = password.ToString(); - } - } -} diff --git a/provisioning/device/samples/Getting Started/X509Sample/X509Sample.csproj b/provisioning/device/samples/Getting Started/X509Sample/X509Sample.csproj deleted file mode 100644 index 7dd3cfb029..0000000000 --- a/provisioning/device/samples/Getting Started/X509Sample/X509Sample.csproj +++ /dev/null @@ -1,32 +0,0 @@ - - - - Exe - net6.0 - 9.0 - Microsoft.Azure.Devices.Provisioning.Client.Samples - - - NU5104 - - - - - - - - - - - - - - - diff --git a/provisioning/device/samples/Getting Started/X509Sample/readme.md b/provisioning/device/samples/Getting Started/X509Sample/readme.md deleted file mode 100644 index a67859aede..0000000000 --- a/provisioning/device/samples/Getting Started/X509Sample/readme.md +++ /dev/null @@ -1,61 +0,0 @@ -# Provisioning Device Client Sample - X.509 Attestation - -## Overview - -This is a quick tutorial with the steps to register a device in the Microsoft Azure IoT Hub Device Provisioning Service using X.509 certificates locally generated. - -## How to run the sample - -Ensure that all prerequisite steps presented in [samples](../) have been performed. - -The sample code is set up to use X.509 certificates stored within a password-protected PKCS12 formatted file (certificate.pfx). To generate a self-signed certificate run the following command: - -`powershell .\GenerateTestCertificate.ps1` - -You can optionally pass the DeviceId and generated certificate validity duration to the powershell script: - -`powershell .\GenerateTestCertificate.ps1 -deviceName "iothubx509device1" -certificateValidityInYears 10` - -The script will prompt for a PFX password. The same password must be used when running the sample. - -In your Device Provisioning Service go to "Manage enrollments" and select "Individual Enrollments". -Select "Add" then fill in the following: -Mechanism: X.509 -Certificate: Select the public key 'certificate.cer' file. - -To run the sample, in a developer command prompt enter: `dotnet run -s ` - -> Replace `IdScope` with the value found within the Device Provisioning Service Overview tab. -> To see a full list of parameters, run `dotnet run -?`. - -Continue by following the instructions presented in the sample console window. - -## Using your certificates - -The SDK requires an [X509Certificate2](https://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate2(v=vs.110).aspx) object with private key ([HasPrivateKey](https://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate2.hasprivatekey(v=vs.110).aspx)==true) and, optionally, the certificate chain within an [X509Certificate2Colection](https://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate2collection(v=vs.110).aspx) object. - -This can be achieved by changing the following line: - -```C# - using var security = new SecurityProviderX509Certificate(certificate); -``` - -to - -```C# - var myCertificate = new X509Certificate2("myCertificate.pfx", "mypassword"); - var myChain = new X509Certificate2Collection(); - - // Comment out the below line if you do not have a .p7b file (e.g. if you generated certificates using the tool below) - myChain.Import("myChain.p7b"); - - using var security = new SecurityProviderX509Certificate(myCertificate, myChain); -``` - -A tool for creating _test_ certificates is available at https://github.com/Azure/azure-iot-sdk-c/blob/master/tools/CACertificates/CACertificateOverview.md - -If you generate _test_ certificates as an administrator using the above tool, please note you must run the sample as administrator as well. - -If a Windows compatible Hardware Security Module is used, the certificate must be obtained by opening it from the Certificate Store using [X509Store](https://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509store(v=vs.110).aspx). - -On Linux, .NET Core is using OpenSSL. Using [PInvoke](https://msdn.microsoft.com/en-us/library/55d3thsc.aspx) it is possible to configure the OpenSSL Engine to use a Hardware Security Module and create an X509Certificate2 object from the context.