C# IoT Device SDK, IotHubUnauthorizedAccess only when using X.509 Cert to GetFileUploadSasUriAsync

huangapple go评论123阅读模式
英文:

C# IoT Device SDK, IotHubUnauthorizedAccess only when using X.509 Cert to GetFileUploadSasUriAsync

问题

I'm putting together a test harness for IoT as an internal reference for our company.
我正在组建一个IoT的测试工具,作为我们公司的内部参考。

I can switch between SymmetricKey and X509 Certs, provision either using DPS and run tests against the endpoints we're interested in.
我可以在SymmetricKey和X509证书之间切换,使用DPS提供其中之一,并对我们感兴趣的端点运行测试。

As I come to test File Upload functionality, when using SymmetricKey, I can request and post a file to the storage account. Using exactly the same method to do the same with X509 cert as the authentication method, I encounter the issue below.
当我要测试文件上传功能时,使用SymmetricKey,我可以请求并上传文件到存储账户。但当我使用X509证书作为认证方式时,使用完全相同的方法进行操作时,我遇到了以下问题。

When using X509 using the same 'DeviceClient' instance, I can send data, update and recall twins, Send C2D messages and invoke methods. Only GetFileUploadSasUriAsync encounters this issue and I'm stumped.
当使用相同的“DeviceClient”实例使用X509时,我可以发送数据,更新和回收双生对象,发送C2D消息并调用方法。只有GetFileUploadSasUriAsync方法遇到了这个问题,我感到困惑。

Line which generates the error:
生成错误的代码行:

"FileUploadSasUriResponse sasUri = await
_deviceClient.GetFileUploadSasUriAsync(fileUploadSasUriRequest, CancellationToken.None);"

What am I doing wrong?
我做错了什么?

CODE
代码

InitialiseIoTClient
初始化IoT客户端

var certPath = AppDomain.CurrentDomain.BaseDirectory + storedConfig.CertName;
var certificate = new X509Certificate2(certPath, storedConfig.CertPassword);
var security = new SecurityProviderX509Certificate(certificate);
var auth = new DeviceAuthenticationWithX509Certificate(storedConfig.DeviceName, certificate);
IoTDeviceClient = DeviceClient.Create(storedConfig.AssignedIoTHub, auth, TransportType.Mqtt);
IoTDeviceClient.SetRetryPolicy(new ExponentialBackoff(5, new TimeSpan(0, 1, 30), new TimeSpan(0, 1, 30), new TimeSpan(0, 1, 15)));
IoTDeviceClient.OpenAsync().Wait();

FileOperations Class
文件操作类

public class FileOperations
{
readonly DeviceClient _deviceClient;

  1. public static LocalConfigStore ConfigStore = new LocalConfigStore();
  2. /// <summary>
  3. /// Load the client and start listening for file upload notifications
  4. /// </summary>
  5. internal FileOperations()
  6. {
  7. _deviceClient = Program.IoTDeviceClient;
  8. ReceiveFileUploadNotificationAsync();
  9. }
  10. /// <summary>
  11. /// This method is used to upload a file to the IoT Hub
  12. /// </summary>
  13. public async void UploadFile()
  14. {
  15. // Generate a large file to upload
  16. var commonOps = new Utils.Common();
  17. var testFilePath = commonOps.GenerateLargeFile();
  18. // Create stream
  19. using var fileStreamSource = new FileStream(testFilePath, FileMode.Open);
  20. var fileName = Path.GetFileName(testFilePath);
  21. var fileUploadTime = Stopwatch.StartNew();
  22. // Get the SAS URI for the file upload
  23. var fileUploadSasUriRequest = new FileUploadSasUriRequest
  24. {
  25. BlobName = fileName
  26. };
  27. FileUploadSasUriResponse sasUri = await _deviceClient.GetFileUploadSasUriAsync(fileUploadSasUriRequest, CancellationToken.None);
  28. Uri uploadUri = sasUri.GetBlobUri();
  29. Console.WriteLine($"Uploading file {fileName} to {uploadUri}.");
  30. // Upload the file to blob storage
  31. var blockBlobClient = new BlockBlobClient(uploadUri);
  32. await blockBlobClient.UploadAsync(fileStreamSource, new BlobUploadOptions());
  33. // Notify IoT Hub that the file upload is complete
  34. var successfulFileUploadCompletionNotification = new FileUploadCompletionNotification
  35. {
  36. // Mandatory. Must be the same value as the correlation id returned in the sas uri response
  37. CorrelationId = sasUri.CorrelationId,
  38. // Mandatory. Will be present when service client receives this file upload notification
  39. IsSuccess = true,
  40. // Optional, user defined status code. Will be present when service client receives this file upload notification
  41. StatusCode = 200,
  42. // Optional, user-defined status description. Will be present when service client receives this file upload notification
  43. StatusDescription = "Success"
  44. };
  45. // Notify IoT Hub that the file upload is complete
  46. await _deviceClient.CompleteFileUploadAsync(successfulFileUploadCompletionNotification);
  47. fileUploadTime.Stop();
  48. Console.WriteLine("File upload completed successfully.");
  49. Console.WriteLine($"Time to upload file: {fileUploadTime.Elapsed}.");
  50. Console.WriteLine("Deleting Test File.");
  51. fileStreamSource.Dispose();
  52. File.Delete(testFilePath);
  53. Console.WriteLine("press enter to continue.");
  54. }
  55. /// <summary>
  56. /// This method is used to receive file upload notifications
  57. /// </summary>
  58. private async void ReceiveFileUploadNotificationAsync()
  59. {
  60. var connectionString = ConfigurationManager.AppSettings["ConnectionStringIotHubOwner"];
  61. // Create service client to receive file upload notifications
  62. ServiceClient serviceClient = ServiceClient.CreateFromConnectionString(connectionString);
  63. // Get file upload notification receiver
  64. var notificationReceiver = serviceClient.GetFileNotificationReceiver();
  65. Console.WriteLine("\nReceiving file upload notification from service");
  66. while (true)
  67. {
  68. // Wait for file upload notification
  69. var fileUploadNotification = await notificationReceiver.ReceiveAsync();
  70. if (fileUploadNotification == null) continue;
  71. Console.ForegroundColor = ConsoleColor.Yellow;
  72. Console.WriteLine("Received file upload notification: {0}", string.Join(", ", fileUploadNotification.BlobName));
  73. Console.ResetColor();
  74. await notificationReceiver.CompleteAsync(fileUploadNotification);
  75. }
  76. }

}
错误
错误

{"Message":"ErrorCode:IotHubUnauthorizedAccess;Unauthorized","ExceptionMessage":"Tracking ID:2d210xxxxxxxxe3afdc-G:0-TimeStamp:08/04/2023 15:48:25"}

at Microsoft.Azure.Devices.Client.Transport.HttpClientHelper.d__22.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Azure.Devices.Client.Transport.HttpClientHelper.d__182.MoveNext() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Azure.Devices.Client.Transport.HttpTransportHandler.<GetFileUploadSasUriAsync>d__15.MoveNext() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()
at RemoteIoTDeviceConsoleApp.Class.Data.FileOperations.<

英文:

I'm putting together a test harness for IoT as an internal reference for our company.

I can switch between SymmetricKey and X509 Certs, provision either using DPS and run tests against the endpoints we're interested in.

As I come to test File Upload functionality, when using SymmetricKey, I can request and post a file to the storage account. Using exactly the same method to do the same with X509 cert as the authentication method, I encounter the issue below.

When using X509 using the same 'DeviceClient' instance, I can send data, update and recall twins, Send C2D messages and invoke methods. Only GetFileUploadSasUriAsync encounters this issue and I'm stumped.

Line which generates the error:

> "FileUploadSasUriResponse sasUri = await
> _deviceClient.GetFileUploadSasUriAsync(fileUploadSasUriRequest, CancellationToken.None);"

What am I doing wrong?

CODE

InitialiseIoTClient

  1. var certPath = AppDomain.CurrentDomain.BaseDirectory + storedConfig.CertName;
  2. Console.WriteLine($&quot;Loading the certificate...&quot;);
  3. using X509Certificate2 certificate = new X509Certificate2(certPath, storedConfig.CertPassword);
  4. using var security = new SecurityProviderX509Certificate(certificate);
  5. using var auth = new DeviceAuthenticationWithX509Certificate(storedConfig.DeviceName, certificate);
  6. IoTDeviceClient = DeviceClient.Create(storedConfig.AssignedIoTHub, auth, TransportType.Mqtt);
  7. IoTDeviceClient.SetRetryPolicy(new ExponentialBackoff(5, new TimeSpan(0, 1, 30), new TimeSpan(0, 1, 30), new TimeSpan(0, 1, 15)));
  8. IoTDeviceClient.OpenAsync().Wait();

FileOperations Class

  1. public class FileOperations
  2. {
  3. readonly DeviceClient _deviceClient;
  4. public static LocalConfigStore ConfigStore = new LocalConfigStore();
  5. /// &lt;summary&gt;
  6. /// Load the client and start listening for file upload notifications
  7. /// &lt;/summary&gt;
  8. internal FileOperations()
  9. {
  10. _deviceClient = Program.IoTDeviceClient;
  11. ReceiveFileUploadNotificationAsync();
  12. }
  13. /// &lt;summary&gt;
  14. /// This method is used to upload a file to the IoT Hub
  15. /// &lt;/summary&gt;
  16. public async void UploadFile()
  17. {
  18. // Generate a large file to upload
  19. var commonOps = new Utils.Common();
  20. var testFilePath = commonOps.GenerateLargeFile();
  21. // Create stream
  22. using var fileStreamSource = new FileStream(testFilePath, FileMode.Open);
  23. var fileName = Path.GetFileName(testFilePath);
  24. var fileUploadTime = Stopwatch.StartNew();
  25. // Get the SAS URI for the file upload
  26. var fileUploadSasUriRequest = new FileUploadSasUriRequest
  27. {
  28. BlobName = fileName
  29. };
  30. FileUploadSasUriResponse sasUri = await _deviceClient.GetFileUploadSasUriAsync(fileUploadSasUriRequest, CancellationToken.None);
  31. Uri uploadUri = sasUri.GetBlobUri();
  32. Console.WriteLine($&quot;Uploading file {fileName} to {uploadUri}.&quot;);
  33. // Upload the file to blob storage
  34. var blockBlobClient = new BlockBlobClient(uploadUri);
  35. await blockBlobClient.UploadAsync(fileStreamSource, new BlobUploadOptions());
  36. // Notify IoT Hub that the file upload is complete
  37. var successfulFileUploadCompletionNotification = new FileUploadCompletionNotification
  38. {
  39. // Mandatory. Must be the same value as the correlation id returned in the sas uri response
  40. CorrelationId = sasUri.CorrelationId,
  41. // Mandatory. Will be present when service client receives this file upload notification
  42. IsSuccess = true,
  43. // Optional, user defined status code. Will be present when service client receives this file upload notification
  44. StatusCode = 200,
  45. // Optional, user-defined status description. Will be present when service client receives this file upload notification
  46. StatusDescription = &quot;Success&quot;
  47. };
  48. // Notify IoT Hub that the file upload is complete
  49. await _deviceClient.CompleteFileUploadAsync(successfulFileUploadCompletionNotification);
  50. fileUploadTime.Stop();
  51. Console.WriteLine($&quot;File upload completed successfully.&quot;);
  52. Console.WriteLine($&quot;Time to upload file: {fileUploadTime.Elapsed}.&quot;);
  53. Console.WriteLine($&quot;Deleting Test File.&quot;);
  54. fileStreamSource.Dispose();
  55. File.Delete(testFilePath);
  56. Console.WriteLine(&quot;press enter to continue.&quot;);
  57. }
  58. /// &lt;summary&gt;
  59. /// This method is used to receive file upload notifications
  60. /// &lt;/summary&gt;
  61. private async void ReceiveFileUploadNotificationAsync()
  62. {
  63. var connectionString = ConfigurationManager.AppSettings[&quot;ConnectionStringIotHubOwner&quot;];
  64. // Create service client to receive file upload notifications
  65. ServiceClient serviceClient = ServiceClient.CreateFromConnectionString(connectionString);
  66. // Get file upload notification receiver
  67. var notificationReceiver = serviceClient.GetFileNotificationReceiver();
  68. Console.WriteLine(&quot;\nReceiving file upload notification from service&quot;);
  69. while (true)
  70. {
  71. // Wait for file upload notification
  72. var fileUploadNotification = await notificationReceiver.ReceiveAsync();
  73. if (fileUploadNotification == null) continue;
  74. Console.ForegroundColor = ConsoleColor.Yellow;
  75. Console.WriteLine(&quot;Received file upload notification: {0}&quot;, string.Join(&quot;, &quot;, fileUploadNotification.BlobName));
  76. Console.ResetColor();
  77. await notificationReceiver.CompleteAsync(fileUploadNotification);
  78. }
  79. }
  80. }

ERROR

  1. {&quot;Message&quot;:&quot;ErrorCode:IotHubUnauthorizedAccess;Unauthorized&quot;,&quot;ExceptionMessage&quot;:&quot;Tracking ID:2d210xxxxxxxxe3afdc-G:0-TimeStamp:08/04/2023 15:48:25&quot;}
  2. at Microsoft.Azure.Devices.Client.Transport.HttpClientHelper.&lt;ExecuteAsync&gt;d__22.MoveNext()
  3. at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
  4. at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
  5. at Microsoft.Azure.Devices.Client.Transport.HttpClientHelper.&lt;PostAsync&gt;d__18`2.MoveNext()
  6. at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
  7. at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
  8. at Microsoft.Azure.Devices.Client.Transport.HttpTransportHandler.&lt;GetFileUploadSasUriAsync&gt;d__15.MoveNext()
  9. at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
  10. at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
  11. at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
  12. at RemoteIoTDeviceConsoleApp.Class.Data.FileOperations.&lt;UploadFile&gt;d__3.MoveNext() in E:\zzzz\xxxx\xxx\xxx\Class\Data\FileOperations.cs:line 53

答案1

得分: 1

错误消息"ErrorCode:IotHubUnauthorizedAccess;Unauthorized" 表明在尝试使用 X.509 证书进行身份验证时,您的设备访问 IoT Hub 服务时遇到了授权问题。以下是使用 X509 证书进行文件上传到 IoT Hub 的示例代码。

  • 使用证书:
  1. var cert = new X509Certificate2("C:\\Tools\\cert\\MyCert.cer");
  2. var auth = new DeviceAuthenticationWithX509Certificate("mydevice", cert);
  3. var DClnt = DeviceClient.Create("HostName", auth);
  • 使用指纹:
  1. private const string CertificateThumbprint = "E9DB5307C576E23009";
  2. private const string IotHubHostName = "sampath.azure-devices.net";
  3. private const string DeviceId = "fa";
  4. private const string FilePath = "C:/Users/Hello.js";
  5. static async Task Main(string[] args)
  6. {
  7. try
  8. {
  9. var auth = new DeviceAuthenticationWithX509Certificate(DeviceId, GetCertificateByThumbprint(CertificateThumbprint));
  10. var deviceClient = DeviceClient.Create(IotHubHostName, auth, TransportType.Http1);
  11. await SendToBlobSample(deviceClient);
  12. }
  13. catch (Exception ex)
  14. {
  15. Console.WriteLine("{0}\n", ex.Message);
  16. if (ex.InnerException != null)
  17. {
  18. Console.WriteLine(ex.InnerException.Message + "\n");
  19. }
  20. }
  21. }
  22. // 其余代码未翻译,仅提供示例部分的翻译

上述代码示例演示了如何使用 X.509 证书进行 IoT Hub 认证并上传文件到 Azure Blob 存储。

英文:

The error message "ErrorCode:IotHubUnauthorizedAccess;Unauthorized" you're encountering indicates an authorization issue when trying to access the IoT Hub service from your device using X.509 certificate authentication.Giving you an example sample of File Upload in IoT Hub using X509 Certs with GetFileUploadSasUriAsync.

  • With Certification:
  1. var cert = new X509Certificate2(&quot;C:\\Tools\\cert\\MyCert.cer&quot;);
  2. var auth = new DeviceAuthenticationWithX509Certificate(&quot;mydevice&quot;, cert);
  3. var DClnt = DeviceClient.Create(&quot;HostName&quot;, auth);
  • With Thumbprint:
  1. private const string CertificateThumbprint = &quot;E9DB5307C576E23009&quot;;
  2. private const string IotHubHostName = &quot;sampath.azure-devices.net&quot;;
  3. private const string DeviceId = &quot;fa&quot;;
  4. private const string FilePath = &quot;C:/Users/Hello.js&quot;;
  5. static async Task Main(string[] args)
  6. {
  7. try
  8. {
  9. var auth = new DeviceAuthenticationWithX509Certificate(DeviceId, GetCertificateByThumbprint(CertificateThumbprint));
  10. var deviceClient = DeviceClient.Create(IotHubHostName, auth, TransportType.Http1);
  11. await SendToBlobSample(deviceClient);
  12. }
  13. catch (Exception ex)
  14. {
  15. Console.WriteLine(&quot;{0}\n&quot;, ex.Message);
  16. if (ex.InnerException != null)
  17. {
  18. Console.WriteLine(ex.InnerException.Message + &quot;\n&quot;);
  19. }
  20. }
  21. }
  22. static async Task SendToBlobSample(DeviceClient deviceClient)
  23. {
  24. var fileStreamSource = new FileStream(FilePath, FileMode.Open);
  25. var fileName = Path.GetFileName(FilePath);
  26. Console.WriteLine(&quot;Uploading File: {0}&quot;, fileName);
  27. var watch = System.Diagnostics.Stopwatch.StartNew();
  28. var fileUploadSasUriRequest = new FileUploadSasUriRequest
  29. {
  30. BlobName = fileName
  31. };
  32. FileUploadSasUriResponse sasUri = await deviceClient.GetFileUploadSasUriAsync(fileUploadSasUriRequest);
  33. Uri uploadUri = sasUri.GetBlobUri();
  34. var blockBlobClient = new BlockBlobClient(uploadUri);
  35. await blockBlobClient.UploadAsync(fileStreamSource, new BlobUploadOptions());
  36. watch.Stop();
  37. Console.WriteLine(&quot;Time to upload file: {0}ms\n&quot;, watch.ElapsedMilliseconds);
  38. Console.WriteLine(&quot;File uploaded to Azure Blob Storage: {0}&quot;, fileName);
  39. var successfulFileUploadCompletionNotification = new FileUploadCompletionNotification
  40. {
  41. CorrelationId = sasUri.CorrelationId,
  42. IsSuccess = true,
  43. StatusCode = 200,
  44. StatusDescription = &quot;Success&quot;
  45. };
  46. await deviceClient.CompleteFileUploadAsync(successfulFileUploadCompletionNotification);
  47. }
  48. static X509Certificate2 GetCertificateByThumbprint(string thumbprint)
  49. {
  50. using (X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser))
  51. {
  52. store.Open(OpenFlags.ReadOnly);
  53. var certificates = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false);
  54. if (certificates.Count &gt; 0)
  55. {
  56. return certificates[0];
  57. }
  58. else
  59. {
  60. throw new Exception(&quot;Certificate not found.&quot;);
  61. }
  62. }
  63. }

C# IoT Device SDK, IotHubUnauthorizedAccess only when using X.509 Cert to GetFileUploadSasUriAsync

C# IoT Device SDK, IotHubUnauthorizedAccess only when using X.509 Cert to GetFileUploadSasUriAsync

huangapple
  • 本文由 发表于 2023年8月5日 00:05:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/76837562.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定