Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

provision by id/key #525

Merged
merged 2 commits into from
Mar 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,37 @@ namespace Meadow.CLI.Commands.DeviceManagement;
[Command("device info", Description = "Get the device info")]
public class DeviceInfoCommand : BaseDeviceCommand<DeviceInfoCommand>
{
[CommandOption("public-key", 'k', Description = "Include the target device's public key in the output", IsRequired = false)]
public bool GetKey { get; set; } = false;

public DeviceInfoCommand(MeadowConnectionManager connectionManager, ILoggerFactory loggerFactory)
: base(connectionManager, loggerFactory)
{
Logger?.LogInformation(Strings.GettingDeviceInfo);
}

protected override async ValueTask ExecuteCommand()
{
var device = await GetCurrentDevice();

Logger?.LogInformation($"{Strings.GettingDeviceInfo}...");

var deviceInfo = await device.GetDeviceInfo(CancellationToken);

if (deviceInfo != null)
{
Logger?.LogInformation(deviceInfo.ToString());
}

if (GetKey)
{
Logger?.LogInformation($"{Strings.GettingDevicePublicKey}...");

var publicKey = await device.GetPublicKey(CancellationToken);

if (!string.IsNullOrWhiteSpace(publicKey))
{
Logger?.LogInformation($"{publicKey}");
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ public class DeviceProvisionCommand : BaseDeviceCommand<DeviceProvisionCommand>
[CommandOption("host", 'h', Description = "Optionally set a host (default is https://www.meadowcloud.co)", IsRequired = false)]
public string? Host { get; set; }

[CommandOption("public-key", 'k', Description = "The public key of the device to provision. If not provided, it will be queried from the configured device.", IsRequired = false)]
public string? PublicKey { get; set; }

[CommandOption("id", 'i', Description = "The unique ID/serial number of the device to provision. If not provided, it will be queried from the configured device.", IsRequired = false)]
public string? SerialNumber { get; set; }

public DeviceProvisionCommand(UserService userService, DeviceService deviceService, MeadowConnectionManager connectionManager, ILoggerFactory loggerFactory)
: base(connectionManager, loggerFactory)
{
Expand Down Expand Up @@ -76,14 +82,31 @@ protected override async ValueTask ExecuteCommand()
CommandExitCode.NotAuthorized);
}

var device = await GetCurrentDevice();
string provisioningID, provisioningName;

var info = await device.GetDeviceInfo(CancellationToken);
if (PublicKey != null)
{
if (SerialNumber == null)
{
throw new CommandException("If a public key is provided, an `id` must also be provided");
}
provisioningID = SerialNumber;
provisioningName = Name ?? string.Empty;
}
else
{
var device = await GetCurrentDevice();

var info = await device.GetDeviceInfo(CancellationToken);

Logger?.LogInformation(Strings.RequestingDevicePublicKey);
var publicKey = await device.GetPublicKey(CancellationToken);
Logger?.LogInformation(Strings.RequestingDevicePublicKey);
PublicKey = await device.GetPublicKey(CancellationToken);

provisioningID = !string.IsNullOrWhiteSpace(info?.ProcessorId) ? info.ProcessorId : info?.SerialNumber;
provisioningName = !string.IsNullOrWhiteSpace(Name) ? Name : info?.DeviceName;
}

if (string.IsNullOrWhiteSpace(publicKey))
if (string.IsNullOrWhiteSpace(PublicKey))
{
throw new CommandException(
Strings.CouldNotRetrievePublicKey,
Expand All @@ -93,18 +116,20 @@ protected override async ValueTask ExecuteCommand()
var delimiters = new string[]
{
"-----END PUBLIC KEY-----\n", // F7 delimiter
"-----END RSA PUBLIC KEY-----\n" // linux/mac/windows delimiter
"-----END PUBLIC KEY-----", // F7 delimiter
"-----END RSA PUBLIC KEY-----\n", // linux/mac/windows delimiter
"-----END RSA PUBLIC KEY-----" // linux/mac/windows delimiter
};

var valid = false;

foreach (var delim in delimiters)
{
var index = publicKey.IndexOf(delim);
var index = PublicKey.IndexOf(delim);
if (index > 0)
{
valid = true;
publicKey = publicKey.Substring(0, publicKey.IndexOf(delim) + delim.Length);
PublicKey = PublicKey.Substring(0, PublicKey.IndexOf(delim) + delim.Length);
break;
}
}
Expand All @@ -117,10 +142,8 @@ protected override async ValueTask ExecuteCommand()
}

Logger?.LogInformation(Strings.ProvisioningWithCloud);
var provisioningID = !string.IsNullOrWhiteSpace(info?.ProcessorId) ? info.ProcessorId : info?.SerialNumber;
var provisioningName = !string.IsNullOrWhiteSpace(Name) ? Name : info?.DeviceName;

var result = await _deviceService.AddDevice(org.Id!, provisioningID!, publicKey, CollectionId, provisioningName, Host, CancellationToken);
var result = await _deviceService.AddDevice(org.Id!, provisioningID!, PublicKey, CollectionId, provisioningName, Host, CancellationToken);

if (result.isSuccess)
{
Expand Down
12 changes: 12 additions & 0 deletions Source/v2/Meadow.Cli/Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@
"commandName": "Project",
"commandLineArgs": "device info"
},
"Device Public Key": {
"commandName": "Project",
"commandLineArgs": "device info -k"
},
"Device Reset": {
"commandName": "Project",
"commandLineArgs": "device reset"
Expand All @@ -43,6 +47,10 @@
"commandName": "Project",
"commandLineArgs": "device clock now"
},
"Config: Set Route local": {
"commandName": "Project",
"commandLineArgs": "config route local"
},
"Config: Set Route Serial": {
"commandName": "Project",
"commandLineArgs": "config route COM4"
Expand Down Expand Up @@ -215,6 +223,10 @@
"commandName": "Project",
"commandLineArgs": "device provision"
},
"Device provision other": {
"commandName": "Project",
"commandLineArgs": "device provision -o christacke6612 --id 2258a2fa0739491aa484a0d6b95c3e15 -k \"-----BEGIN RSA PUBLIC KEY-----\nMIIBigKCAYEA2kj+97LvLa9tZhn9rLBGNgJIEw+Wl+qJXHXW1AmAv3zcytXJ5uGJ\nJjrU7V/y/R6R/TizZRY57puz/mG5BMopdtdNx3Cpfb35SaGmIiSiAVpELci/Ldpd\ntsGJphfSxslVkc3/s2LEZ416pybzGoTb4+KGj+L+GcNYoe6rxFgVJEv3PTlpBWbv\nCUZGBb/0twedNmmXZzq9W79UYIMQaB53fgdH9qFOvBIw9zcG2a6MY/MBGU6nr7BY\nwShjMV9AwP3z1ao6X4nbpfPtBRPjyyyGdVH4bKF7dLgBGZnShmvGfhGpaxWJlBIk\n3IJYgJbd8y5MVVhsJv6AmBmm84dyDX2Tn5wKvZ+Fbmpeez87rosm+C80VnO6Kz4E\nFmIErHGGaoBoX9L7cf33yMwty2glCNW7HYUl/YWJPg+8eyuEjOpGHqJSAW4AlfgY\n0FDNj/AR0Pni0wfQ+DUpBt5i2kgUw0MDWlWVYYbgxmO1VbvofWJwYLYgeiCxNPBj\nopp0RZfm/brRAgMBAAE=\n-----END RSA PUBLIC KEY-----\""
},
"Login": {
"commandName": "Project",
"commandLineArgs": "login"
Expand Down
3 changes: 2 additions & 1 deletion Source/v2/Meadow.Cli/Strings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ public static class Strings
public const string SettingDeviceClock = "Setting device clock...";
public const string InvalidApplicationPath = "Invalid application path";
public const string InvalidParameter = "Invalid parameter";
public const string GettingDeviceInfo = "Getting device info...";
public const string GettingDeviceInfo = "Getting device info";
public const string GettingDevicePublicKey = "Getting device public key";
public const string UnableToGetDeviceInfo = "Unable to get device info";
public const string RetrievingUserAndOrgInfo = "Retrieving your user and organization information...";
public const string MemberOfMoreThanOneOrg = "You are a member of more than 1 organization. Please specify the desired orgId for this device provisioning.";
Expand Down
36 changes: 28 additions & 8 deletions Source/v2/Meadow.Hcom/Connections/LocalConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,18 +97,21 @@ public override Task<string> GetPublicKey(CancellationToken? cancellationToken =
var pkFile = Path.Combine(sshFolder.FullName, "id_rsa.pub");
if (!File.Exists(pkFile))
{
throw new Exception("Public key not found");
throw new Exception("Public key not found. Run 'ssh-keygen -t rsa'");
}

return Task.FromResult(File.ReadAllText(pkFile));
var pkFileContent = File.ReadAllText(pkFile);

if (!pkFileContent.Contains("BEGIN RSA PUBLIC KEY"))
{
pkFileContent = ExecuteWindowsCommandLine("ssh-keygen", $"-e -m pem -f {pkFile}");
}

return Task.FromResult(pkFileContent);
}
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
// ssh-agent sh -c 'ssh-add; ssh-add -L'
throw new PlatformNotSupportedException();
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)
|| RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
// ssh-agent sh -c 'ssh-add; ssh-add -L'
var pubkey = this.ExecuteBashCommandLine("ssh-agent sh -c 'ssh-add; ssh-add -L'");
Expand All @@ -127,6 +130,23 @@ public override Task<string> GetPublicKey(CancellationToken? cancellationToken =
}
}

private string ExecuteWindowsCommandLine(string command, string args)
{
var psi = new ProcessStartInfo()
{
FileName = command,
Arguments = args,
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true
};

using var process = Process.Start(psi);

process?.WaitForExit();

return process?.StandardOutput.ReadToEnd() ?? string.Empty;
}



Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ public MeadowConnectionManager(ISettingsManager settingsManager)
_currentConnection?.Detach();
_currentConnection?.Dispose();

if (route == "local")
{
return new LocalConnection();
}

// try to determine what the route is
string? uri = null;
if (route.StartsWith("http"))
Expand Down
5 changes: 4 additions & 1 deletion Source/v2/Meadow.UsbLib.Core/ILibUsbDevice.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
namespace Meadow.LibUsb;
using System;
using System.Collections.Generic;

namespace Meadow.LibUsb;

public interface ILibUsbProvider
{
Expand Down
5 changes: 2 additions & 3 deletions Source/v2/Meadow.UsbLib.Core/Meadow.UsbLib.Core.csproj
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>10</LangVersion>
</PropertyGroup>

</Project>
2 changes: 2 additions & 0 deletions Source/v2/Meadow.UsbLib/LibUsbDevice.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using LibUsbDotNet.LibUsb;
using System.Collections.Generic;
using System.Linq;

namespace Meadow.LibUsb;

Expand Down
6 changes: 3 additions & 3 deletions Source/v2/Meadow.UsbLib/Meadow.UsbLib.csproj
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<TargetFramework>net5.0</TargetFramework>
<LangVersion>10</LangVersion>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
Expand Down
3 changes: 3 additions & 0 deletions Source/v2/Meadow.UsbLibClassic/ClassicLibUsbDevice.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
using LibUsbDotNet;
using LibUsbDotNet.Main;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Meadow.LibUsb;

Expand Down
6 changes: 3 additions & 3 deletions Source/v2/Meadow.UsbLibClassic/Meadow.UsbLibClassic.csproj
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>10</LangVersion>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
Expand Down
Loading