絶賛AWSしてます。
AWSへの接続はsshです。
PowerShellで繋げって?teraterm先生があるので、今はいいかなー (白目
と、ここでteratermを使っていて困るのが、接続の自動化がされず毎回ユーザー名や秘密鍵の選択をさせられることです。
インフラ担当としては、いい加減にしてくださいとなるわけです。
今回、TeratermとPowerShellを連携かして、なるべく自動化してみたいと思います。
Teratermの自動接続
Teratermには、引数でパラメーターを受ける機能があります。
そう、マクロなんて書かなくてもいいのです。 ((
Tera Term Pro コマンドライン
今回は、公開鍵での接続とします。
今時、パスワード認証……ないですよね。
必要な情報
基本AWSのAMIインスタンスに接続なので、ユーザー名は固定なんですが……まぁ一応!
必要な情報は以下です。
- Teraterm実行ファイルパス(ttermpro.exe)
- 接続先host
- 接続先Port
- sshタイプ
- 認証タイプ
- ユーザー名
- 秘密鍵パス
ようは、以下の形でショートカットを作成すると接続できます。
"C:\Program Files (x86)\teraterm\ttermpro.exe" 192.168.0.100:22 /ssh2 /auth=publickey /user=user /keyfile=D:\key.rsa
追加実装
- 一度入力した内容は、jsonでファイル保持します。
今回の場合は、tterapro.exeと秘密鍵パスと接続先hostです。
- CUIではなくXamlでGUIライクに
Gitコード公開
GitHubで公開しています。
Xaml (GUI) バージョン:
https://github.com/guitarrapc/PowerShellUtil/blob/master/TeraTermConnection/teraterm_xaml.ps1
CUIバージョン:
https://github.com/guitarrapc/PowerShellUtil/blob/master/TeraTermConnection/Enter-Teraterm.ps1
コード公開
「ファイルを開く」のダイアログをだすためのfunctionを定義します。
function Get-File{
[CmdletBinding(
SupportsShouldProcess = $false,
ConfirmImpact = "none"
)]
param
(
[Parameter(
Position = 0
)]
[ValidateNotNullOrEmpty()]
[string]
$Message,
[Parameter(
Position = 1
)]
[ValidateNotNullOrEmpty()]
[string]
$Extention
)
begin
{
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") > $null
$Dialog = New-Object System.Windows.Forms.OpenFileDialog
}
process
{
$Dialog.Title = “Select $Message File”
$Dialog.InitialDirectory = "%UserProfile%”
$Dialog.Filter = $Extention
$result = $Dialog.ShowDialog()
}
end
{
If($result -eq “OK”)
{
$inputFile = $Dialog.FileName
return $inputFile
}
else
{
return "Cancelled"
}
}
}
本体の前にXamlで、ユーザーに雪像先の情報を入力してもらいます。
$loadXaml =@'
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Invoke AWS Teraterm Connection"
FontFamily="consolas"
Height="400" Width="400" Margin="5"
>
<StackPanel>
<Label
Name="labeltera"
Content="TeraTerm execution file"
Height="30" Margin="2"
HorizontalAlignment="Center"
/>
<Button
Name="bOpenFileDialogTera"
Content="Open tterapro.exe"
Height="30" Margin="5"
HorizontalAlignment="Left" VerticalAlignment="Top"
/>
<TextBox
Name="textboxTera"
Text="C:\Program Files (x86)\teraterm\ttermpro.exe"
Background="#00AA88"
Height="25" Margin="5"
/>
<Label
Name="labelkeyFile"
Content="Pem Key :"
Height="30" Margin="2"
HorizontalAlignment="Center"
/>
<Button
Name="bOpenFileDialogkeyFile"
Content="Open Pem File"
Height="30" Margin="5"
HorizontalAlignment="Left" VerticalAlignment="Top"
/>
<TextBox
Name="textboxkeyFile"
Text="C:\Program Files (x86)\teraterm\RSA\rsa.pem"
Background="#00AA88"
Height="25" Margin="5"
/>
<Label
Name="labelip"
Content="Input AWS Server IP or Host Name"
Height="30" Margin="2"
HorizontalAlignment="Center"
/>
<TextBox
Name="textboxIP"
Text=""
Background="#FFFFFF"
Height="25" Margin="10"
/>
<Button
Name="buttonOK"
Content="OK"
FontSize="14"
Foreground="#FFFFFF"
Background="#505050"
Height="40"
Margin="5"
/>
</StackPanel>
</Window>
'@
で、なんちゃってコードびはいxxx
function Show-XAMLSystemTime{
[CmdletBinding(
SupportsShouldProcess = $false,
ConfirmImpact = "none",
DefaultParameterSetName = ""
)]
param
(
[Parameter(
HelpMessage = "Input path of ....",
Position = 0,
Mandatory = $false,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true
)]
[ValidateNotNullOrEmpty()]
[ValidateScript({Test-Path $_.FullName})]
[IO.FileInfo[]]
$path,
[Parameter(
HelpMessage = "Enter tbind xaml @`...`@ to load.",
Position = 0,
Mandatory = $true,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true
)]
[ValidateNotNullOrEmpty()]
[string]
$loadXaml,
[Alias("PassThru")]
[switch]
$PassThrough
)
begin
{
try
{
# Add-Typeでアセンブリをロードする
Add-Type -AssemblyName presentationframework
}
catch
{
#Alread Type added.
}
try
{
[xml]$xaml = $loadXaml
}
catch
{
}
}
process
{
$reader=(New-Object System.Xml.XmlNodeReader $xaml)
$window=[Windows.Markup.XamlReader]::Load( $reader )
$bOpenFileDialogTera = $window.FindName("bOpenFileDialogTera")
$textboxTera = $window.FindName("textboxTera")
$bOpenFileDialogkeyFile = $window.FindName("bOpenFileDialogkeyFile")
$textboxkeyFile = $window.FindName("textboxkeyFile")
$textboxIP = $window.FindName("textboxIP")
$buttonOK = $window.FindName("buttonOK")
$jsonFile = "Connection.json"
#Check json file exist or not
if(Test-Path .\$jsonFile)
{
$jsonRead = Get-Content $jsonFile | ConvertFrom-Json
$textboxTera.Text = $jsonRead.tera
$textboxkeyFile.Text = $jsonRead.keyFile
$textboxIP.Text = $jsonRead.ip
$textboxIP.Text = $jsonRead.ip
}
#bOpenFileDialogTera
$buttonTera_clicked = $bOpenFileDialogTera.add_Click
$buttonTera_clicked.Invoke({
$teraResult = Get-File -Message "tterapro.exe" -Extention “exe files (*.exe)|*.exe”
if ($teraResult -ne "Cancelled")
{
$textboxTera.Text = $TeraResult
}
})
#bOpenFileDialogkeyFile
$buttonkeyFile_clicked = $bOpenFileDialogkeyFile.add_Click
$buttonkeyFile_clicked.Invoke({
$keyFileResult = Get-File -Message ".pem" -Extention “Pem files (*.pem)|*.pem”
if ($keyFileResult -ne "Cancelled")
{
$textboxkeyFile.Text = $keyFileResult
}
})
#buttonOK event to close window
$buttonOK_clicked = $buttonOK.add_Click
$buttonOK_clicked.Invoke({
$Window.close()})
#buttonOK event to close window
$buttonOK_clicked = $buttonOK.add_Click
$buttonOK_clicked.Invoke({
$Window.close()})
# region / TODO: Keydown Eventの検知
<#
#textboxip Keydown Event
$textboxIP_keydown = $textboxIP.KeyDown
if($textboxIP_keydown.Key -eq [System.Windows.Forms.Keys]::Enter)
{
$textboxIP_keydown.Invoke({$textboxkeyFile.Text = 123})
}
#>
}
end
{
$window.ShowDialog() > $null
#return to Powershell
$result = [PSCustomObject]@{
tera=$textboxTera.Text
keyFile=$textboxkeyFile.Text
ip=$textboxIP.Text.Trim()
}
$result | ConvertTo-Json -Compress | Out-File .\connection.json
return $result
}
}
teratermに接続するためのfunction作成します。
function Enter-Teraterm{
パラメータは同様に。
[CmdletBinding(
SupportsShouldProcess = $false,
ConfirmImpact = "none"
)]
param
(
[Parameter(
HelpMessage = "Input path of Terterm Pro execution file 'ttermpro.exe' exists",
Position = 0
)]
[ValidateScript({Test-Path $_})]
[ValidateNotNullOrEmpty()]
[string]
$teraterm="C:\Program Files (x86)\teraterm\ttermpro.exe",
[Parameter(
HelpMessage = "Input Connecting Hot IP/NetBIOS to connect",
Position = 1
)]
[ValidateNotNullOrEmpty()]
[string]
$ip,
[Parameter(
HelpMessage = "Input Port number to connect",
Position = 2
)]
[ValidateNotNullOrEmpty()]
[int]
$port="22",
[Parameter(
HelpMessage = "Input SSH type : default value = /ssh2",
Position = 3
)]
[ValidateSet("/ssh1","/ssh2")]
[ValidateNotNullOrEmpty()]
[string]
$ssh="/ssh2",
[Parameter(
HelpMessage = "Input Authentication type : default value = publickey",
Position = 4
)]
[ValidateSet("password","publickey","challenge","pageant")]
[ValidateNotNullOrEmpty()]
[string]
$auth="publickey",
[Parameter(
HelpMessage = "Input username to login : default value = ec2-user",
Position = 5
)]
[ValidateNotNullOrEmpty()]
[string]
$user="ec2-user",
[Parameter(
HelpMessage = "Input rsa key path : default value = C:\Program Files (x86)\teraterm\RSA\purplehosts.pem",
Position = 6
)]
[ValidateScript({Test-Path $_})]
[ValidateNotNullOrEmpty()]
[string]
$keyFile="C:\Program Files (x86)\teraterm\RSA\purplehosts.pem"
)
プロセスと引数を触るため、.NETを呼び出します。
begin
{
try
{
$process = New-Object System.Diagnostics.Process
}
catch
{
}
try
{
$process.StartInfo = New-Object System.Diagnostics.ProcessStartInfo @($teraterm)
}
catch
{
}
}
接続先のIPとportをstringがっちゃんこします。
process
{
try
{
[string]$connection = $ip + ":" + $port
}
catch
{
}
実行ディレクトリを指示して…
$process.StartInfo.WorkingDirectory = (Get-Location).Path
引数を指定し
$process.StartInfo.Arguments = "$connection $ssh /auth=$auth /user=$user /keyfile=$keyFile"
tterapro.exeを起動します。
$process.Start() > $null
最後にfunctionを閉じます。
}
後は実行しましょう。
まずはXaml画面を表示して、ユーザー操作の値を受け取ります。
# Open XAML View and get paramters
$WPFresult = Show-XAMLSystemTime -loadXaml $loadXaml
次に、Xaml結果をコマンドレットに渡して実行します。
# Connection (Keyfile not allowed contain space)
Enter-Teraterm -teraterm $WPFresult.tera -ip $WPFresult.IP -keyFile $WPFresult.keyFile
ぜひ、機会がある人はどうぞ!
眠いのでスクリーンショットは許してくださいー
コード全文です。(18/Apr/2013)
function Get-File{
[CmdletBinding(
SupportsShouldProcess = $false,
ConfirmImpact = "none"
)]
param
(
[Parameter(
Position = 0
)]
[ValidateNotNullOrEmpty()]
[string]
$Message,
[Parameter(
Position = 1
)]
[ValidateNotNullOrEmpty()]
[string]
$Extention
)
begin
{
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") > $null
$Dialog = New-Object System.Windows.Forms.OpenFileDialog
}
process
{
$Dialog.Title = “Select $Message File”
$Dialog.InitialDirectory = "%UserProfile%”
$Dialog.Filter = $Extention
$result = $Dialog.ShowDialog()
}
end
{
If($result -eq “OK”)
{
$inputFile = $Dialog.FileName
return $inputFile
}
else
{
return "Cancelled"
}
}
}
function Show-XAMLSystemTime{
[CmdletBinding(
SupportsShouldProcess = $false,
ConfirmImpact = "none",
DefaultParameterSetName = ""
)]
param
(
[Parameter(
HelpMessage = "Input path of ....",
Position = 0,
Mandatory = $false,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true
)]
[ValidateNotNullOrEmpty()]
[ValidateScript({Test-Path $_.FullName})]
[IO.FileInfo[]]
$path,
[Parameter(
HelpMessage = "Enter tbind xaml @`...`@ to load.",
Position = 0,
Mandatory = $true,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true
)]
[ValidateNotNullOrEmpty()]
[string]
$loadXaml,
[Alias("PassThru")]
[switch]
$PassThrough
)
begin
{
try
{
# Add-Typeでアセンブリをロードする
Add-Type -AssemblyName presentationframework
}
catch
{
#Alread Type added.
}
try
{
[xml]$xaml = $loadXaml
}
catch
{
}
}
process
{
$reader=(New-Object System.Xml.XmlNodeReader $xaml)
$window=[Windows.Markup.XamlReader]::Load( $reader )
$bOpenFileDialogTera = $window.FindName("bOpenFileDialogTera")
$textboxTera = $window.FindName("textboxTera")
$bOpenFileDialogkeyFile = $window.FindName("bOpenFileDialogkeyFile")
$textboxkeyFile = $window.FindName("textboxkeyFile")
$textboxIP = $window.FindName("textboxIP")
$buttonOK = $window.FindName("buttonOK")
$jsonFile = "Connection.json"
#Check json file exist or not
if(Test-Path .\$jsonFile)
{
$jsonRead = Get-Content $jsonFile | ConvertFrom-Json
$textboxTera.Text = $jsonRead.tera
$textboxkeyFile.Text = $jsonRead.keyFile
$textboxIP.Text = $jsonRead.ip
$textboxIP.Text = $jsonRead.ip
}
#bOpenFileDialogTera
$buttonTera_clicked = $bOpenFileDialogTera.add_Click
$buttonTera_clicked.Invoke({
$teraResult = Get-File -Message "tterapro.exe" -Extention “exe files (*.exe)|*.exe”
if ($teraResult -ne "Cancelled")
{
$textboxTera.Text = $TeraResult
}
})
#bOpenFileDialogkeyFile
$buttonkeyFile_clicked = $bOpenFileDialogkeyFile.add_Click
$buttonkeyFile_clicked.Invoke({
$keyFileResult = Get-File -Message ".pem" -Extention “Pem files (*.pem)|*.pem”
if ($keyFileResult -ne "Cancelled")
{
$textboxkeyFile.Text = $keyFileResult
}
})
#buttonOK event to close window
$buttonOK_clicked = $buttonOK.add_Click
$buttonOK_clicked.Invoke({
$Window.close()})
#buttonOK event to close window
$buttonOK_clicked = $buttonOK.add_Click
$buttonOK_clicked.Invoke({
$Window.close()})
# region / TODO: Keydown Eventの検知
<#
#textboxip Keydown Event
$textboxIP_keydown = $textboxIP.KeyDown
if($textboxIP_keydown.Key -eq [System.Windows.Forms.Keys]::Enter)
{
$textboxIP_keydown.Invoke({$textboxkeyFile.Text = 123})
}
#>
}
end
{
$window.ShowDialog() > $null
#return to Powershell
$result = [PSCustomObject]@{
tera=$textboxTera.Text
keyFile=$textboxkeyFile.Text
ip=$textboxIP.Text.Trim()
}
$result | ConvertTo-Json -Compress | Out-File .\connection.json
return $result
}
}
$loadXaml =@'
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Invoke AWS Teraterm Connection"
FontFamily="consolas"
Height="400" Width="400" Margin="5"
>
<StackPanel>
<Label
Name="labeltera"
Content="TeraTerm execution file"
Height="30" Margin="2"
HorizontalAlignment="Center"
/>
<Button
Name="bOpenFileDialogTera"
Content="Open tterapro.exe"
Height="30" Margin="5"
HorizontalAlignment="Left" VerticalAlignment="Top"
/>
<TextBox
Name="textboxTera"
Text="C:\Program Files (x86)\teraterm\ttermpro.exe"
Background="#00AA88"
Height="25" Margin="5"
/>
<Label
Name="labelkeyFile"
Content="Pem Key :"
Height="30" Margin="2"
HorizontalAlignment="Center"
/>
<Button
Name="bOpenFileDialogkeyFile"
Content="Open Pem File"
Height="30" Margin="5"
HorizontalAlignment="Left" VerticalAlignment="Top"
/>
<TextBox
Name="textboxkeyFile"
Text="C:\Program Files (x86)\teraterm\RSA\rsa.pem"
Background="#00AA88"
Height="25" Margin="5"
/>
<Label
Name="labelip"
Content="Input AWS Server IP or Host Name"
Height="30" Margin="2"
HorizontalAlignment="Center"
/>
<TextBox
Name="textboxIP"
Text=""
Background="#FFFFFF"
Height="25" Margin="10"
/>
<Button
Name="buttonOK"
Content="OK"
FontSize="14"
Foreground="#FFFFFF"
Background="#505050"
Height="40"
Margin="5"
/>
</StackPanel>
</Window>
'@
function Enter-Teraterm{
[CmdletBinding(
SupportsShouldProcess = $false,
ConfirmImpact = "none"
)]
param
(
[Parameter(
HelpMessage = "Input path of Terterm Pro execution file 'ttermpro.exe' exists",
Position = 0
)]
[ValidateScript({Test-Path $_})]
[ValidateNotNullOrEmpty()]
[string]
$teraterm="C:\Program Files (x86)\teraterm\ttermpro.exe",
[Parameter(
HelpMessage = "Input Connecting Hot IP/NetBIOS to connect",
Position = 1
)]
[ValidateNotNullOrEmpty()]
[string]
$ip,
[Parameter(
HelpMessage = "Input Port number to connect",
Position = 2
)]
[ValidateNotNullOrEmpty()]
[int]
$port="22",
[Parameter(
HelpMessage = "Input SSH type : default value = /ssh2",
Position = 3
)]
[ValidateSet("/ssh1","/ssh2")]
[ValidateNotNullOrEmpty()]
[string]
$ssh="/ssh2",
[Parameter(
HelpMessage = "Input Authentication type : default value = publickey",
Position = 4
)]
[ValidateSet("password","publickey","challenge","pageant")]
[ValidateNotNullOrEmpty()]
[string]
$auth="publickey",
[Parameter(
HelpMessage = "Input username to login : default value = ec2-user",
Position = 5
)]
[ValidateNotNullOrEmpty()]
[string]
$user="ec2-user",
[Parameter(
HelpMessage = "Input rsa key path : default value = C:\Program Files (x86)\teraterm\RSA\rsa.pem",
Position = 6
)]
[ValidateScript({Test-Path $_})]
[ValidateNotNullOrEmpty()]
[string]
$keyFile="C:\Program Files (x86)\teraterm\RSA\rsa.pem"
)
begin
{
try
{
$process = New-Object System.Diagnostics.Process
}
catch
{
}
try
{
$process.StartInfo = New-Object System.Diagnostics.ProcessStartInfo @($teraterm)
}
catch
{
}
}
process
{
try
{
[string]$connection = $ip + ":" + $port
}
catch
{
}
$process.StartInfo.WorkingDirectory = (Get-Location).Path
#"C:\Program Files (x86)\teraterm\ttermpro.exe" 192.168.0.100:22 /ssh2 /auth=publickey /user=user /keyfile=D:\key.rsa
$process.StartInfo.Arguments = "$connection $ssh /auth=$auth /user=$user `"/keyfile=$keyFile`""
$process.Start() > $null
}
}
# Open XAML View and get paramters
$WPFresult = Show-XAMLSystemTime -loadXaml $loadXaml
# Connection (Keyfile not allowed contain space)
Enter-Teraterm -teraterm $WPFresult.tera -ip $WPFresult.IP -keyFile $WPFresult.keyFile