/// <summary> /// Initializes the VPN certificate authority as well as the server and root user's certificates and keys. /// </summary> private void CreateVpnCredentials() { // This is a bit tricky: We're going to invoke the [neon vpn ca ...] command to // initialize the hive's certificate authority files. This command must be // run in the [neon-cli] container so we need to detect whether we're already // running in the tool container and do the right thing. // // Note that the we can't pass the original hive definition file to the command // because the command will shim into a [neon-cli] container and any environment // variable references within the definition won't be able to be resolved because // the environment variables aren't mapped into the container. // // The solution is to persist a temporary copy of the loaded hive definition // that has already resolved environment variables to the neonFORGE temp folder // and pass that. The user's neonFORGE folder is encrypted in place so doing this // will be as safe as storing hive logins there. string tempCaFolder; string tempDefPath; if (HiveHelper.InToolContainer) { tempCaFolder = "/shim/ca"; } else { tempCaFolder = Path.Combine(Program.HiveTempFolder, Guid.NewGuid().ToString("D")); } tempDefPath = Path.Combine(HiveHelper.GetTempFolder(), $"{Guid.NewGuid().ToString("D").ToLowerInvariant()}.def.json"); File.WriteAllText(tempDefPath, NeonHelper.JsonSerialize(hive.Definition, Formatting.Indented)); try { Directory.CreateDirectory(tempCaFolder); // Execute the [neon vpn cert init ...] command to generate the certificate // authority files and the root client certificate and key and then load // the files into a [VpnCaFiles] object. var neonExecutable = NeonHelper.IsWindows ? "neon.cmd" : "neon"; if (HiveHelper.InToolContainer) { Program.Execute(neonExecutable, "vpn", "ca", tempDefPath, tempCaFolder); } else { Program.Execute(neonExecutable, "vpn", "ca", tempDefPath, tempCaFolder); } vpnCaFiles = VpnCaFiles.LoadFolder(tempCaFolder); } finally { if (Directory.Exists(tempCaFolder)) { Directory.Delete(tempCaFolder, recursive: true); } if (File.Exists(tempDefPath)) { File.Delete(tempDefPath); } } }