From b1007ff0d2ea027988a5c353a936b5f6cc28c8e3 Mon Sep 17 00:00:00 2001 From: wyunchi-ms Date: Tue, 11 Aug 2020 17:15:20 +0800 Subject: [PATCH 1/2] Add new switch GenerateSshKey to generate SSH keys if necessary. --- src/Aks/Aks/ChangeLog.md | 1 + src/Aks/Aks/Commands/NewAzureRmAks.cs | 80 ++++++++++++++++++++ src/Aks/Aks/Properties/Resources.Designer.cs | 29 ++++++- src/Aks/Aks/Properties/Resources.resx | 9 +++ src/Aks/Aks/help/Az.Aks.md | 1 + src/Aks/Aks/help/New-AzAksCluster.md | 19 ++++- 6 files changed, 136 insertions(+), 3 deletions(-) diff --git a/src/Aks/Aks/ChangeLog.md b/src/Aks/Aks/ChangeLog.md index 0c6e5e5290a9..2adc9f74d4c2 100644 --- a/src/Aks/Aks/ChangeLog.md +++ b/src/Aks/Aks/ChangeLog.md @@ -18,6 +18,7 @@ - Additional information about change #1 --> ## Upcoming Release +* Add parameter `GenerateSshKey` for `New-AzAksCluster`. ## Version 1.2.0 * Removed `ClientIdAndSecret` to `ServicePrincipalIdAndSecret` and set `ClientIdAndSecret` as an alias [#12381]. diff --git a/src/Aks/Aks/Commands/NewAzureRmAks.cs b/src/Aks/Aks/Commands/NewAzureRmAks.cs index 9066d99aec6f..c1297889f2c7 100644 --- a/src/Aks/Aks/Commands/NewAzureRmAks.cs +++ b/src/Aks/Aks/Commands/NewAzureRmAks.cs @@ -13,7 +13,11 @@ // ---------------------------------------------------------------------------------- using System; +using System.Diagnostics; +using System.IO; using System.Management.Automation; +using System.Runtime.InteropServices; + using Microsoft.Azure.Commands.Aks.Models; using Microsoft.Azure.Commands.Aks.Properties; using Microsoft.Azure.Management.ContainerService; @@ -31,10 +35,16 @@ public class NewAzureRmAks : NewKubeBase [Parameter(Mandatory = false, HelpMessage = "Create cluster even if it already exists")] public SwitchParameter Force { get; set; } + [Parameter( + Mandatory = false, + HelpMessage = "Generate ssh key file to {HOME}/.ssh/id_rsa.")] + public SwitchParameter GenerateSshKey { get; set; } + public override void ExecuteCmdlet() { base.ExecuteCmdlet(); PreValidate(); + PrepareParameter(); Action action = () => { @@ -72,6 +82,76 @@ private void PreValidate() if ((this.IsParameterBound(c => c.NodeMinCount) || this.IsParameterBound(c => c.NodeMaxCount) || this.EnableNodeAutoScaling.IsPresent) && !(this.IsParameterBound(c => c.NodeMinCount) && this.IsParameterBound(c => c.NodeMaxCount) && this.EnableNodeAutoScaling.IsPresent)) throw new PSInvalidCastException(Resources.AksNodePoolAutoScalingParametersMustAppearTogether); + + if (this.IsParameterBound(c => c.GenerateSshKey) && this.IsParameterBound(c => c.SshKeyValue)) + { + throw new ArgumentException(string.Format(Resources.DonotUseGenerateSshKeyWithSshKeyValue)); + } + } + + private void VerifySshKeyGenBinaryExist() + { + using (Process process = new Process()) + { + if ((RuntimeInformation.IsOSPlatform(OSPlatform.Windows))) + { + process.StartInfo.FileName = "where.exe"; + } + else + { + process.StartInfo.FileName = "whereis"; + } + process.StartInfo.Arguments = "ssh-keygen"; + process.StartInfo.UseShellExecute = false; + process.StartInfo.RedirectStandardOutput = true; + + process.Start(); + process.WaitForExit(); + + string result = process.StandardOutput.ReadLine(); + if (result.Contains("not found") || result.Contains("Could not find") || result.Trim().Equals("ssh-keygen:")) + { + throw new ArgumentException(Resources.EnableSsh); + } + + if (process.ExitCode != 0) + { + throw new ArgumentException(Resources.EnableSsh); + } + } + } + + private string GenerateSshKeyValue() + { + VerifySshKeyGenBinaryExist(); + String generateSshKeyPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".ssh", "id_rsa"); ; + if (File.Exists(generateSshKeyPath)) + { + throw new ArgumentException(string.Format(Resources.DefaultSshKeyAlreadyExist)); + } + using (Process process = new Process()) + { + process.StartInfo.FileName = "ssh-keygen"; + process.StartInfo.Arguments = "-f " + generateSshKeyPath; + process.StartInfo.UseShellExecute = false; + process.StartInfo.RedirectStandardInput = true; + process.StartInfo.RedirectStandardError = true; + process.StartInfo.RedirectStandardOutput = true; + process.Start(); + + Console.WriteLine(process.StandardOutput.ReadToEnd()); + + process.WaitForExit(); + } + return GetSshKey(generateSshKeyPath); + } + + protected void PrepareParameter() + { + if (this.IsParameterBound(c => c.GenerateSshKey)) + { + SshKeyValue = GenerateSshKeyValue(); + } } } } diff --git a/src/Aks/Aks/Properties/Resources.Designer.cs b/src/Aks/Aks/Properties/Resources.Designer.cs index 128107ed86c3..69ff2f7684be 100644 --- a/src/Aks/Aks/Properties/Resources.Designer.cs +++ b/src/Aks/Aks/Properties/Resources.Designer.cs @@ -19,7 +19,7 @@ namespace Microsoft.Azure.Commands.Aks.Properties { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { @@ -240,6 +240,15 @@ internal static string CreatingClusterAgentPool { } } + /// + /// Looks up a localized string similar to Default ssh key already exists. Please use -SshKeyVaule.. + /// + internal static string DefaultSshKeyAlreadyExist { + get { + return ResourceManager.GetString("DefaultSshKeyAlreadyExist", resourceCulture); + } + } + /// /// Looks up a localized string similar to Deploying your managed Kubernetes cluster.. /// @@ -258,6 +267,15 @@ internal static string DidNotFindJob { } } + /// + /// Looks up a localized string similar to Don't use -GenerateSshKey and -SshKeyVaule at the same time.. + /// + internal static string DonotUseGenerateSshKeyWithSshKeyValue { + get { + return ResourceManager.GetString("DonotUseGenerateSshKeyWithSshKeyValue", resourceCulture); + } + } + /// /// Looks up a localized string similar to Downloading kubectl from internet. /// @@ -321,6 +339,15 @@ internal static string DoYouWantToOverwriteExistingFile { } } + /// + /// Looks up a localized string similar to Cannot find ssh-keygen. Please enable OpenSSH on your local machine.. + /// + internal static string EnableSsh { + get { + return ResourceManager.GetString("EnableSsh", resourceCulture); + } + } + /// /// Looks up a localized string similar to Fetching the clusterAdmin kubectl config. /// diff --git a/src/Aks/Aks/Properties/Resources.resx b/src/Aks/Aks/Properties/Resources.resx index c4c53e7c3624..c9155953090d 100644 --- a/src/Aks/Aks/Properties/Resources.resx +++ b/src/Aks/Aks/Properties/Resources.resx @@ -369,4 +369,13 @@ Windows agent pool name can not be longer than 6 characters. + + Don't use -GenerateSshKey and -SshKeyVaule at the same time. + + + Default ssh key already exists. Please use -SshKeyVaule. + + + Cannot find ssh-keygen. Please enable OpenSSH on your local machine. + \ No newline at end of file diff --git a/src/Aks/Aks/help/Az.Aks.md b/src/Aks/Aks/help/Az.Aks.md index 7d6121602855..2d1031952943 100644 --- a/src/Aks/Aks/help/Az.Aks.md +++ b/src/Aks/Aks/help/Az.Aks.md @@ -49,3 +49,4 @@ Stop the Kubectl SSH tunnel created in Start-AzKubernetesDashboard. ### [Update-AzAksNodePool](Update-AzAksNodePool.md) Update node pool in a managed cluster. + diff --git a/src/Aks/Aks/help/New-AzAksCluster.md b/src/Aks/Aks/help/New-AzAksCluster.md index a7b273726ac8..38f70489358f 100644 --- a/src/Aks/Aks/help/New-AzAksCluster.md +++ b/src/Aks/Aks/help/New-AzAksCluster.md @@ -21,8 +21,8 @@ New-AzAksCluster [-Force] [-NodeVmSetType ] [-NodeVnetSubnetID ] [-Location ] [-LinuxProfileAdminUserName ] [-DnsNamePrefix ] [-KubernetesVersion ] [-NodeName ] [-NodeMinCount ] [-NodeMaxCount ] [-EnableNodeAutoScaling] [-NodeCount ] [-NodeOsDiskSize ] [-NodeVmSize ] - [-SshKeyValue ] [-AsJob] [-Tag ] [-DefaultProfile ] [-WhatIf] - [-Confirm] [] + [-SshKeyValue ] [-GenerateSshKey] [-AsJob] [-Tag ] + [-DefaultProfile ] [-WhatIf] [-Confirm] [] ``` ## DESCRIPTION @@ -154,6 +154,21 @@ Accept pipeline input: False Accept wildcard characters: False ``` +### -GenerateSshKey +Generate ssh key file to {HOME}/.ssh/id_rsa. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ### -KubernetesVersion The version of Kubernetes to use for creating the cluster. From 3287ef1299cc18c3df510a5ad12dd9cba1640eb8 Mon Sep 17 00:00:00 2001 From: wyunchi-ms Date: Wed, 9 Sep 2020 14:26:37 +0800 Subject: [PATCH 2/2] Handle the exception of white space in path. --- src/Aks/Aks/Commands/NewAzureRmAks.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Aks/Aks/Commands/NewAzureRmAks.cs b/src/Aks/Aks/Commands/NewAzureRmAks.cs index c1297889f2c7..06fa194bb3a2 100644 --- a/src/Aks/Aks/Commands/NewAzureRmAks.cs +++ b/src/Aks/Aks/Commands/NewAzureRmAks.cs @@ -132,7 +132,7 @@ private string GenerateSshKeyValue() using (Process process = new Process()) { process.StartInfo.FileName = "ssh-keygen"; - process.StartInfo.Arguments = "-f " + generateSshKeyPath; + process.StartInfo.Arguments = String.Format("-f \"{0}\"", generateSshKeyPath); process.StartInfo.UseShellExecute = false; process.StartInfo.RedirectStandardInput = true; process.StartInfo.RedirectStandardError = true;