diff --git a/src/AzureIoTHub.Portal/Client/Pages/Gateways/Detail.razor b/src/AzureIoTHub.Portal/Client/Pages/Gateways/Detail.razor index 04c801ced..b5f7889a6 100644 --- a/src/AzureIoTHub.Portal/Client/Pages/Gateways/Detail.razor +++ b/src/AzureIoTHub.Portal/Client/Pages/Gateways/Detail.razor @@ -255,12 +255,16 @@ else public async Task ShowConnectionString() { + gateway.SymmetricKey = await this.Http.GetStringAsync($"api/Gateways/{gateway.DeviceId}/ConnectionString"); + var parameter = new DialogParameters(); + parameter.Add(nameof(Gateway.DeviceId), gateway.DeviceId); parameter.Add(nameof(Gateway.EndPoint), gateway.EndPoint); parameter.Add(nameof(Gateway.SymmetricKey), gateway.SymmetricKey); - var result = await DialogService.Show("ConnectionString gateway ", parameter).Result; + + DialogService.Show("ConnectionString gateway ", parameter); } public async Task DeleteDeviceAsync() diff --git a/src/AzureIoTHub.Portal/Server/Controllers/GatewaysController.cs b/src/AzureIoTHub.Portal/Server/Controllers/GatewaysController.cs index 12fdd3dfb..0052a1c32 100644 --- a/src/AzureIoTHub.Portal/Server/Controllers/GatewaysController.cs +++ b/src/AzureIoTHub.Portal/Server/Controllers/GatewaysController.cs @@ -11,6 +11,7 @@ namespace AzureIoTHub.Portal.Server.Controllers using System.Threading.Tasks; using AzureIoTHub.Portal.Server.Helpers; using AzureIoTHub.Portal.Server.Interfaces; + using AzureIoTHub.Portal.Server.Managers; using AzureIoTHub.Portal.Server.Services; using AzureIoTHub.Portal.Shared.Models; using AzureIoTHub.Portal.Shared.Security; @@ -36,17 +37,20 @@ public class GatewaysController : ControllerBase private readonly RegistryManager registryManager; private readonly IConfiguration configuration; private readonly IDeviceService devicesService; + private readonly IConnectionStringManager connectionStringManager; public GatewaysController( IConfiguration configuration, ILogger logger, RegistryManager registryManager, + IConnectionStringManager connectionStringManager, IDeviceService service) { this.logger = logger; this.registryManager = registryManager; this.configuration = configuration; this.devicesService = service; + this.connectionStringManager = connectionStringManager; } /// @@ -140,6 +144,19 @@ public async Task Get(string deviceId) } } + [HttpGet("{deviceId}/ConnectionString")] + public async Task GetSymmetricKey(string deviceId) + { + try + { + return this.Ok(await this.connectionStringManager.GetSymmetricKey(deviceId)); + } + catch (Exception e) + { + return this.BadRequest(e.Message); + } + } + /// /// this function create a device with the twin information. /// diff --git a/src/AzureIoTHub.Portal/Server/Helpers/DeviceHelper.cs b/src/AzureIoTHub.Portal/Server/Helpers/DeviceHelper.cs index f398e5a9d..45b322be6 100644 --- a/src/AzureIoTHub.Portal/Server/Helpers/DeviceHelper.cs +++ b/src/AzureIoTHub.Portal/Server/Helpers/DeviceHelper.cs @@ -25,6 +25,7 @@ public static string RetrieveSymmetricKey(string deviceId, AttestationMechanism // then we get the symmetricKey SymmetricKeyAttestation symmetricKey = attestationMechanism.GetAttestation() as SymmetricKeyAttestation; using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(symmetricKey.PrimaryKey)); + return Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(deviceId))); } diff --git a/src/AzureIoTHub.Portal/Server/Managers/ConnectionStringManager.cs b/src/AzureIoTHub.Portal/Server/Managers/ConnectionStringManager.cs new file mode 100644 index 000000000..69696fc04 --- /dev/null +++ b/src/AzureIoTHub.Portal/Server/Managers/ConnectionStringManager.cs @@ -0,0 +1,33 @@ +// Copyright (c) CGI France - Grand Est. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace AzureIoTHub.Portal.Server.Managers +{ + using System.Threading.Tasks; + using AzureIoTHub.Portal.Server.Helpers; + using AzureIoTHub.Portal.Server.Services; + + public class ConnectionStringManager : IConnectionStringManager + { + private readonly IDeviceService deviceService; + + public ConnectionStringManager(IDeviceService deviceService) + { + this.deviceService = deviceService; + } + + public async Task GetSymmetricKey(string deviceId) + { + try + { + var attestationMechanism = await this.deviceService.GetDpsAttestionMechanism(); + + return DeviceHelper.RetrieveSymmetricKey(deviceId, attestationMechanism); + } + catch (System.Exception e) + { + throw new System.Exception(e.Message); + } + } + } +} diff --git a/src/AzureIoTHub.Portal/Server/Managers/IConnectionStringManager.cs b/src/AzureIoTHub.Portal/Server/Managers/IConnectionStringManager.cs new file mode 100644 index 000000000..520bb219b --- /dev/null +++ b/src/AzureIoTHub.Portal/Server/Managers/IConnectionStringManager.cs @@ -0,0 +1,12 @@ +// Copyright (c) CGI France - Grand Est. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace AzureIoTHub.Portal.Server.Managers +{ + using System.Threading.Tasks; + + public interface IConnectionStringManager + { + Task GetSymmetricKey(string deviceId); + } +} diff --git a/src/AzureIoTHub.Portal/Server/Startup.cs b/src/AzureIoTHub.Portal/Server/Startup.cs index 5dcdb2acb..ce35e68c8 100644 --- a/src/AzureIoTHub.Portal/Server/Startup.cs +++ b/src/AzureIoTHub.Portal/Server/Startup.cs @@ -100,11 +100,11 @@ public void ConfigureServices(IServiceCollection services) services.AddTransient(sp => new BlobServiceClient(configuration.StorageAccountConnectionString)); services.AddTransient(sp => new TableClientFactory(configuration.StorageAccountConnectionString)); services.AddTransient(); - // services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); services.AddTransient(); @@ -210,6 +210,7 @@ internal abstract class ConfigHandler { protected const string IoTHubConnectionStringKey = "IoTHub:ConnectionString"; protected const string DPSConnectionStringKey = "IoTDPS:ConnectionString"; + protected const string DPSDefaultEnrollmentGroupeKey = "IoTDPS:DefaultEnrollmentGroupe"; protected const string MsalScopeNameKey = "MsalSettings:ScopeName"; protected const string MsalInstanceKey = "MsalSettings:Instance"; @@ -242,6 +243,8 @@ internal static ConfigHandler Create(IWebHostEnvironment env, IConfiguration con internal abstract string DPSConnectionString { get; } + internal abstract string DPSDefaultEnrollmentGroupe { get; } + internal abstract string StorageAccountConnectionString { get; } internal abstract string MsalScopeName { get; } @@ -284,6 +287,8 @@ internal ProductionConfigHandler(IConfiguration config) internal override string DPSConnectionString => this.config.GetConnectionString(DPSConnectionStringKey); + internal override string DPSDefaultEnrollmentGroupe => this.config[DPSDefaultEnrollmentGroupeKey]; + internal override string StorageAccountConnectionString => this.config.GetConnectionString(StorageAccountConnectionStringKey); internal override string MsalScopeName => this.config[MsalScopeNameKey]; @@ -326,6 +331,8 @@ internal DevelopmentConfigHandler(IConfiguration config) internal override string DPSConnectionString => this.config[DPSConnectionStringKey]; + internal override string DPSDefaultEnrollmentGroupe => this.config[DPSDefaultEnrollmentGroupeKey]; + internal override string StorageAccountConnectionString => this.config[StorageAccountConnectionStringKey]; internal override string MsalScopeName => this.config[MsalScopeNameKey];