Skip to content

Commit

Permalink
updates for Mac PEM provisioning
Browse files Browse the repository at this point in the history
  • Loading branch information
ctacke committed Dec 5, 2023
1 parent 1be3659 commit 793baeb
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 83 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class DeviceProvisionCommand : BaseDeviceCommand<DeviceProvisionCommand>
[CommandOption("name", 'n', Description = "Device friendly name", IsRequired = false)]
public string? Name { get; set; }

[CommandOption("host", 'e', Description = "Optionally set a host (default is https://www.meadowcloud.co)", IsRequired = false)]
[CommandOption("host", 'h', Description = "Optionally set a host (default is https://www.meadowcloud.co)", IsRequired = false)]
public string? Host { get; set; }

public DeviceProvisionCommand(DeviceService deviceService, MeadowConnectionManager connectionManager, ILoggerFactory loggerFactory)
Expand Down Expand Up @@ -82,54 +82,16 @@ protected override async ValueTask ExecuteCommand()

var info = await connection.Device!.GetDeviceInfo(CancellationToken);

if (info == null)
{
Logger?.LogError($"Unable to get device info");
return;
}

Logger?.LogInformation("Requesting device public key (this will take a minute)...");
var publicKey = await connection.Device.GetPublicKey(CancellationToken);

var delimList = new string[]
{
"-----END PUBLIC KEY-----",
"-----END RSA PUBLIC KEY-----"
};
var delim = "-----END RSA PUBLIC KEY-----\n";
publicKey = publicKey.Substring(0, publicKey.IndexOf(delim) + delim.Length);

foreach (var delim in delimList)
{
var i = publicKey.IndexOf(delim);
if (i >= 0)
{
publicKey = publicKey.Substring(0, publicKey.IndexOf(delim) + delim.Length);
break;
}
}

Logger?.LogInformation("Provisioning device with Meadow.Cloud...");

string provisioningID;

// prefer processorID (since the F7 works that way)
if (!string.IsNullOrEmpty(info.ProcessorId))
{
provisioningID = info.ProcessorId;
}
else
{
if (info.SerialNumber == null)
{
Logger?.LogError($"Unable to get device serial number or processor ID");
return;
}

provisioningID = info.SerialNumber;
}

// upper-case to prevent issues where clients and provisioning differ
provisioningID = provisioningID.ToUpper();

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);
Expand Down
55 changes: 14 additions & 41 deletions Source/v2/Meadow.Hcom/Connections/LocalConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public LocalConnection()
}
using (var key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Cryptography\"))
{
info.Add("SerialNo", (key?.GetValue("MachineGuid")?.ToString() ?? "Unknown").Trim().ToUpper());
info.Add("SerialNo", (key?.GetValue("MachineGuid")?.ToString() ?? "Unknown").Trim());
}
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
Expand All @@ -58,7 +58,7 @@ public LocalConnection()
_deviceInfo = new DeviceInfo(info);
}

return Task.FromResult<DeviceInfo?>(_deviceInfo);
return Task.FromResult< DeviceInfo?>(_deviceInfo);
}

private string ExecuteBashCommandLine(string command)
Expand All @@ -68,6 +68,7 @@ private string ExecuteBashCommandLine(string command)
FileName = "/bin/bash",
Arguments = $"-c \"{command}\"",
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true
};
Expand All @@ -76,30 +77,14 @@ private string ExecuteBashCommandLine(string command)

process?.WaitForExit();

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

private string ExecuteWindowsCommandLine(string command, string args)
{
var psi = new ProcessStartInfo()
{
FileName = command,
Arguments = args,
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true
};
var stdout = process?.StandardOutput.ReadToEnd() ?? string.Empty;
var stderr = process?.StandardError.ReadToEnd() ?? string.Empty;

using var process = Process.Start(psi);

process?.WaitForExit();

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

public override Task<string> GetPublicKey(CancellationToken? cancellationToken = null)
{
// DEV NOTE: this *must* be in PEM format: i.e. -----BEGIN RSA PUBLIC KEY----- ... -----END RSA PUBLIC KEY----

if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
Expand All @@ -117,37 +102,25 @@ public override Task<string> GetPublicKey(CancellationToken? cancellationToken =
throw new Exception("Public key not found");
}

var pkFileContent = File.ReadAllText(pkFile);
if (!pkFileContent.Contains("BEGIN RSA PUBLIC KEY", StringComparison.OrdinalIgnoreCase))
{
// need to convert
pkFileContent = ExecuteWindowsCommandLine("ssh-keygen", $"-e -m pem -f {pkFile}");
}

return Task.FromResult(pkFileContent);
return Task.FromResult(File.ReadAllText(pkFile));
}
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
// this will generate a PEM output *assuming* the key has already been created
var keygenOutput = ExecuteBashCommandLine("ssh-keygen -f id_rsa -e -m pem");
if (!keygenOutput.Contains("BEGIN RSA PUBLIC KEY", StringComparison.OrdinalIgnoreCase))
{
// probably no key generated
throw new Exception("Unable to retrieve a public key. Please run 'ssh-keygen -t rsa'");
}

return Task.FromResult(keygenOutput);
// ssh-agent sh -c 'ssh-add; ssh-add -L'
throw new PlatformNotSupportedException();
}
else if (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'");
if (!pubkey.Contains("BEGIN RSA PUBLIC KEY", StringComparison.OrdinalIgnoreCase))

if (pubkey.StartsWith("ssh-rsa"))
{
var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".ssh", "id_rsa.pub");
pubkey = ExecuteBashCommandLine($"ssh-keygen -f {path} -e -m pem");
// convert to PEM format
pubkey = this.ExecuteBashCommandLine("ssh-keygen -f ~/.ssh/id_rsa.pub -m 'PEM' -e");
}

return Task.FromResult(pubkey);
}
else
Expand Down

0 comments on commit 793baeb

Please sign in to comment.