2019/07/24(水)ホスト選択式ログイン自動化マクロ(マスターパスワード利用版)

はてブ数 2019/07/24 16:03 Macro::macro サンプル

ホスト選択式ログイン自動化マクロ(マスターパスワード利用版)

このサンプルマクロは、以下の仕様を満たすものとします。

マクロの目的

選択したホストに対するアクセス情報を保持し、同一ホストに対する 2 回目以降のパスワード入力を回避します。
選択可能なホストは以下の通りとします。

プロトコル想定OS備考
SSHUNIX / LinuxWindows でも sshd サーバを稼働すれば可能。
RDPWindowsLinux でも xrdp 等を稼働すれば可能。
TelnetCisco IOSローカルからアクセスするスイッチングハブ等

また、毎回デフォルト設定で良いか問い合わせ、アクセス情報の変更があった場合も収集情報を保持することとします。
この機能により、アクセス先情報を変更した同一ファイルを複数実行しても、パスワードファイル内でコンフリクトしないようになります。

ただし、保持するアクセス情報はサーバへのログインとは別に、毎回のパスワード入力を必須とします。
この目的のために Tera Term の getpasswd コマンドで作成したパスワードファイルを、暗号化または解凍します。

アーカイブ作成・解凍のための前提アプリに、コマンドライン版 7zip を利用します。
7zip は、GNU LGPL ライセンスによって開発されているアーカイバです。
https://sevenzip.osdn.jp/

利用可能環境

Teraterm
依存する Tera Term バージョン:Tera Term 4.78 以降*1

利用する Tera Term コマンド:
種別:制御Ver機能の簡易説明
callサブルーチンをコールする。
endマクロの実行そのものを終了する。
execcmndTTL コマンド を実行する。
gotoラベルへジャンプする。
if,then,elseif,else,endif条件分岐
pause休止する。
returnサブルーチンを抜け、メインルーチンへ戻る。
種別:文字列操作Ver機能の簡易説明
expandenv4.71以降環境変数文字列を展開する。
sprintf24.62以降フォーマットされた出力を返す。
strspecial4.67以降特殊文字を変換する。
種別:ファイル操作Ver機能の簡易説明
filedeleteファイルを削除する。
filesearchファイルまたはフォルダがあるか確かめる。
foldersearch4.69以降フォルダがあるか確かめる。
getdirMACRO の現在のディレクトリを得る。
makepathフルパス名を作成する。
種別:パスワードコマンドVer機能の簡易説明
getpasswordパスワードを読み出す。
ndex/macro/spec/cmd/passwordboxパスワードを入力するためのダイアログボックスを開く。
4.54以降特殊文字の解釈を制御するオプションの追加。
種別:その他Ver機能の簡易説明
execアプリケーションを起動する。
4.63以降起動したアプリケーションの終了を待つオプションの追加。
4.78以降カレントディレクトリを指定するオプションの追加。
inputbox文字列を入力するためのダイアログボックスを開く。
4.53以降デフォルト入力文字を設定するオプションの追加。
4.54以降特殊文字の解釈を制御するオプションの追加。
messageboxダイアログボックスを開き、ユーザーにメッセージを知らせる。
4.54以降特殊文字の解釈を制御するオプションの追加。
4.60以降キャンセル時にマクロ停止を確認する機能の追加。
yesnoboxダイアログボックスを開き、ユーザーに「はい」/「いいえ」を選択させる。
4.54以降特殊文字の解釈を制御するオプションの追加。
4.60以降キャンセル時にマクロ停止を確認する機能の追加。

マクロの使い方

実行タイミング
任意のタイミングで実行可能です。
マクロの指定方法
詳細は TeraTerm マクロの使い方 を参照してください。
ttpmacro.exe を利用する場合
ファイルの拡張子 .ttl を ttpmacro.exe へ関連付けしておきます。
.ttl ファイルをダブルクリック等で実行します。
ttermpro.exe を利用する場合
ttermpro.exe を利用する場合は、起動時にオプションへ /M=xxx.ttl のように指定します。
メニューから実行する場合
Tera Term メニューから「コントロール(O)」→「マクロ(M)」を選択します。
対象ファイルを選択して「開く」ボタンをクリックすると、実行されます。
実行時の入力情報
入力する情報は、「マスターパスワード」→「種別選択」→「ホスト選択」の順になります。
ユーザ名は「★アカウント関係」のデフォルトユーザ名すべてを '' (Null) へ変更した場合に入力します。

マスターパスワードで解凍するパスワードファイルに、対象のユーザパスワードがない場合は「ログインパスワード」を入力します。
マスターパスワード
マスターパスワードの入力画面が表示されます。

パスワードファイルを暗号化/復号化するためのパスワードを入力してください。

RDPSecureLogin_1.png


マスターパスワードはパスワードファイルを管理するための情報であるため、毎回必ず入力します。
種別選択
利用するプロトコルを選択する画面が表示されます。

host_select_1.png

ホスト選択
利用プロトコルでアクセス可能なホストが表示されます*2

host_select_2.png

ログインパスワード入力
初回アクセス時、アクセス先ホスト用のパスワード入力画面が表示されます。
ユーザ名に対応したパスワードを入力してください。

host_select_3.png


"ユーザ名+ホスト名" が過去にアクセスした情報と合致した場合は、表示されません。
過去に入力した情報を利用します。
リモートアクセス
選択した各プロトコルで、ホストへ接続します。

*1 : 保存する文字コードによっては Tera Term バージョン 4.102 以降

*2 : ホスト自体は、事前にユーザ自身で書き換える必要があります。

コード

著作権情報

このサンプルマクロに関する著作権は、当サイト管理者が所有しています。
著作権者
神場 和也
ライセンス
3条項BSDライセンス
関連情報
(なし)

サンプルコード

ファイルダウンロード
SelectAccess_v2.zip
※ 解凍してご利用ください。
項目内容
文字コードShift JIS
実行確認バージョンTera Term Ver 4.103
初版公開2019/7/24
備考下記コピペ用ソースコードをファイルに保存したものです。
※ UTF-8 で保存した場合は、Tera Term Ver 4.102 以降で実行する必要があります。詳細は マクロファイルの仕様 を参照してください。
コピペ用
以下のソースコードをファイルに保存のうえ、★ の項目を必要に応じて修正してご利用ください。

対象となる ★ の項目の参考情報です。
★ 対象項目ユーザで修正する内容
アカウント関係デフォルトで使用するユーザ名を指定します。
_defaultUserName[1] ~ [3] が '' の場合は、_defaultUserName[0] の情報が利用されます。
すべて '' の場合は実行ごとにユーザ名を入力します。
ファイル関係管理するパスワードファイルの名前を指定します。
デフォルトの保存先 (カレント) は、マクロファイルのある場所です。
相対パスも絶対パスも利用可能です。
ディレクトリ関係コマンドライン版 7zip の保存先等を指定します。
SSH 対象SSH プロトコルで選択するホスト名を指定します。
ホストを増やす場合は strdim で指定している数も増やしてください。
RDP 対象RDP プロトコルで選択するホスト名を指定します。
Telnet 対象Telnet プロトコルで選択するホスト名を指定します。
RDP 待機時間RDP 接続時に Windows へ一時的に登録したアカウント情報を、削除するまでの待機時間を指定してください。
Telnet における入力プロンプトTelnet 接続時に表示される、アカウント入力プロンプトを指定してください。
パスワード登録に最低限必要な文字数ホスト接続時に利用するパスワード*3 の最低文字数を指定してください。
getpassword は messagebox や yesnobox のようにキャンセルした際、何らかの文字が混入することがあります。
混入してしまうと意図しないパスワード入力が行われて、アクセスのできないファイルが作成されてしまいます。
ゴミを出力させないための対策です。
strdimstrdim で定義するマクロに利用できるデータ型列については、以下を参照してください。
・リモートアクセスを行うマクロ
想定ファイル名:SelectAccess.ttl
; ssh2 / RDP / telnet login macro of Tera Term

; File: SelectAccess.ttl
; Description: auto login
; Environment: generic
; Update: 2019/7/28
; Author: Kazuya Jimba

;;; 変数定義 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; 以下、★ の項目は必要に応じて内容を修正してください。

;; ★アカウント関係
; ユーザ名の文字数 0 なら [0] のユーザを利用します。
; [0] の文字数が 0 ならば、inputbox で入力します。
; [1] ~ [3] は、アクセス種別に連動します。
strdim _defaultUserName 4

; デフォルトユーザの指定例
;_defaultUserName[0] = 'User'
;_defaultUserName[1] = 'SSHUser'
;_defaultUserName[2] = 'RDPUser'
;_defaultUserName[3] = 'TelnetUser'

; 指定しない場合は、ユーザ名を毎回入力する。
_defaultUserName[0] = ''		; 他の指定が 0 の場合のデフォルト
_defaultUserName[1] = ''		; SSH を指定した場合のデフォルト
_defaultUserName[2] = ''		; RDP を指定した場合のデフォルト
_defaultUserName[3] = ''		; Switch を指定した場合のデフォルト

;; ★ファイル関係
_defaultPassFile = 'SecurityLogin.dat'
_defaultPassZip  = 'SecurityLogin.zip'

;; ★ディレクトリ関係
getdir _pwdir

;; ★コマンドライン版 7zip 関係
_7zipDir = 'C:\7za920'
_7zipExe = '7za.exe'

;; ★SSH 対象
strdim axSSH 5
axSSH[0] = '192.168.0.10'
axSSH[1] = '192.168.0.11'
axSSH[2] = '192.168.0.12'
axSSH[3] = '192.168.0.13'
axSSH[4] = '192.168.0.14'

;; ★RDP 対象
strdim axRdp 2
axRdp[0] = '192.168.0.20'
axRdp[1] = '192.168.0.21'

;; ★Telnet 対象
strdim axSwitch 2
axSwitch[0] = '192.168.0.1'
axSwitch[1] = '192.168.0.2'

;; ★RDP 接続時における、Windows 登録情報削除までの待機時間
_DeleteWaitTime = 15

;; ★Telnet における入力プロンプト
UsernamePrompt = 'Username:'
PasswordPrompt = 'Password:'

;; ★パスワード登録に最低限必要な文字数
; 当マクロを利用する場合、ホストへの接続パスワードは、
; 必ず 2 文字以上にしてください。
; getpassword は messagebox や yesnobox のようにキャンセルしても 
; パスワード入力されたとみなされてしまう仕様への対応です。
_passStrLen = 2

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 【注意】
; 以下の項目を修正すると、マクロの動作に多大な影響があります。
; 修正した場合は、マクロ全体を見直してください。
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; 接続関係
_TypeSSHstr = "SSH (UNIX / Linux)"
_TypeRDPstr = "RDP (Windows)"
_TypeTelnet = "Telnet (Switch)"

;; アクセス種別
; SSH / RDP / Telnet の振り分けです。
strdim class 3

class[0] = _TypeSSHstr
class[1] = _TypeRDPstr
class[2] = _TypeTelnet

;; パス生成
makepath _7zip  _7zipDir _7zipExe
makepath _pwdat _pwdir   _defaultPassFile
makepath _pwzip _pwdir   _defaultPassZip

;;; メイン処理 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; 環境ファイルの確認

; パスワードファイルの有無 (0であるのが正解)
_target = _pwdat
call subFileSearch
_flagPassFile = result

; zip ファイルの有無
_target = _pwzip
call subFileSearch
_flagPassZip = result

; コマンドライン版 7zip の有無
_target = _7zip
call subFileSearch
if result <> 1 then
  goto ErrorEnd_No7zip
endif

;; パスワード情報取得

_msgtitle = 'マスターパスワード入力'
_msgline = '暗号化/復号化のためのマスターパスワードが必要です。\nマスターパスワードを入力してください。'
strspecial _msgline
passwordbox _msgline _msgtitle 1
_filepassword = inputstr

; もし .dat があるなら処理の続行を確認。
if _flagPassFile == 1 then
  sprintf2 _msg "%s が存在します。\n処理を続行しますか?" _defaultPassFile
  strspecial _msg
  yesnobox _msg 'Error'
  if result then
    ; YES
    ; もし Zip があったらエラー。
    if _flagPassZip <> 0 then
      sprintf2 _msg "ZIP ファイル(%s)が存在します。\nいずれかを削除し、当スクリプトの稼働環境を修復してください。" _defaultPassZip
      strspecial _msg
      messagebox _msg 'Error'
      end
    endif

  else
    ; NO
    goto NormalEnd

  endif

elseif _flagPassFile == 0 then
  ; .dat がなければ、zip を探す。
  if _flagPassZip == 1 then
    ; zip が存在すれば解凍
    sprintf2 _ExtractCmd "%s x -tzip -p%s %s -o%s" _7zip _filepassword _pwzip _pwdir
    exec _ExtractCmd 'hide' 1

    ; result (errorlevel) が 0 なら成功とみなして zip ファイルを削除する。
    if result == 0 then
      filedelete _pwzip

    elseif result then
      ; メッセージ生成
      sprintf2 msg 'パスワードファイルの解凍に失敗しました。\n\n 対象ファイル: %s\n Exit Code: %d' _pwzip result
      sprintf2 title '解凍失敗'
      strspecial msg
      messagebox msg title

      ;; 7zip エラーコードの意味(7zip のヘルプより引用)
      ; Code Meaning 
      ; 0    No error 
      ; 1    Warning (Non fatal error(s)). For example, one or more files were locked by some other application, so they were not compressed. 
      ; 2    Fatal error 
      ; 7    Command line error 
      ; 8    Not enough memory for operation 
      ; 255  User stopped the process 

      ; もしファイルがあれば削除
      ; (パスワードを間違えると、内容の破壊されたパスワードファイルができることがある)
      _target = _pwdat
      call subFileSearch
      if result  == 1 then
        filedelete _pwdat
      endif

      end

    endif

  elseif _flagPassZip < 0 then
    ; ディレクトリならエラー終了
    goto ErrorEnd

  endif

else
  ; ディレクトリならエラー終了
  goto ErrorEnd

endif

;; アクセス先選択
sprintf2 msg   "アクセス先接続タイプを選択してください。"
sprintf2 title "種別選択"

listbox msg title class
_classType = result

if _classType == 0 then
  _arrType  = _TypeSSHstr
  _arrClass = 'axSSH'
  _defPort  = 22

elseif _classType == 1 then
  _arrType  = _TypeRDPstr
  _arrClass = 'axRdp'
  _defPort  = 3389

elseif _classType == 2 then
  _arrType  = _TypeTelnet
  _arrClass = 'axSwitch'
  _defPort  = 23

else
  ; キャンセルを選択
  if _flagPassZip == 1 then
    ;; もし解凍していたら、再度アーカイブしておく。
    call subArchive
  endif

  end

endif

; メッセージ生成
sprintf2 msg     "アクセス先を選択してください。"
sprintf2 title   "%s 選択" _arrType
sprintf2 list_cmd "listbox msg title %s" _arrClass

; アクセス先ホスト選択
execcmnd list_cmd

if result < 0 then
  ; キャンセルを選択
  if _flagPassZip == 1 then
    ;; もし解凍していたら、再度アーカイブしておく。
    call subArchive
  endif

  end

endif

sprintf2 host_cmd "hostname = %s[%d]" _arrClass result
execcmnd host_cmd

;;; アカウント情報入力

; デフォルトユーザ名の文字数確認
strlen _defaultUserName[_classType + 1]
_userlen = result

; もし種別毎に設定されていれば
if _userlen > 0 then
  ; 種別毎にデフォルト名を設定
  UserName = _defaultUserName[_classType + 1]

else
  ; デフォルト名も文字数を確認して
  strlen _defaultUserName[0]
  if result then
    ; 指定があれば利用
    UserName = _defaultUserName[0]

  else
    ; 指定のない場合は入力
    sprintf2 msg   "ホストへアクセスするユーザを入力してください。\n\n 対象ホスト: %s" hostname
    sprintf2 title "アカウント入力"
    strspecial msg
    inputbox msg title
    UserName = inputstr

  endif

endif

sprintf2 account "%s@%s" UserName hostname
getpassword _defaultPassFile account password

strlen password
if result < _passStrLen then
  if _flagPassZip == 1 then
    ;; もし解凍していたら、再度アーカイブしておく。
    call subArchive
  endif

  end

endif

; 必要な情報は全て変数へ格納したので、ファイルはアーカイブしておく。

call subArchive

;; アクセス種別ごとにサブルーチンの呼び出しを選択

if _classType == 0 then
  ; SSH
  call subAccessSSH

elseif _classType == 1 then
  ; RDP
  call subAccessRDP

elseif _classType == 2 then
  ; Telnet
  call subAccessTelnet

endif

;;; 終了処理 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
:NormalEnd

end

:ErrorEnd_No7zip
sprintf2 msg "以下のファイルが存在しません。\n\n 対象ファイル:%s" _7zip
strspecial msg
messagebox msg 'ファイルエラー'

end

;;; サブルーチン ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

:subFileSearch
; #################################
; # サブルーチン:subFileSearch
; #################################

;; 対象を確認する。
;; -1 対象はディレクトリ
;;  0 存在しない
;;  1 対象はファイル
;messagebox _target ':subFileSearch'
filesearch _target
if result = 1 then
  ; ファイルかフォルダが存在するので、選別
  foldersearch _target
  if result = 1 then
    ; 対象はフォルダ
    _result = -1
  else
    ; 対象はファイル
    _result = 1
  endif
else
  ; ファイルもフォルダも存在しない
  _result = 0
endif

result = _result

return

:subAccessSSH
; #################################
; # サブルーチン:subAccessSSH
; #################################

sprintf2 _Parameter "%s:%d /ssh /auth=password /user=%s /passwd=%s" hostname _defPort username password

;; アクセス時のパラメータ隠匿用
connect '/DS'

;; ログイン
connect _Parameter

;; ログイン確認
if result < 2 then
	messagebox 'Not connected.' 'Error'
	end
endif

return

:subAccessRDP
; #################################
; # サブルーチン:subAccessRDP
; #################################

;;; 接続処理

; Windows へのアカウント登録
sprintf2 line "cmdkey /generic:TERMSRV/%s /user:%s /pass:%s" hostname username password
exec line

; Remote Desktop 接続
;RDP = "%windir%\system32\mstsc.exe"
expandenv RDP "%windir%\system32\mstsc.exe"

sprintf2 CMD "%s /v:%s" RDP hostname
exec CMD

; RDP 接続できたら、以下のマクロはバックグランドで動作。

;;; 接続後処理

;; 登録情報の削除

; 接続中に Windows への登録情報を削除してしまうことがあるため、待機
pause _DeleteWaitTime

; 登録した情報の削除コマンド
sprintf2 line "cmdkey /delete:TERMSRV/%s" hostname
exec line

return

:subAccessTelnet
; #################################
; # サブルーチン:subAccessTelnet
; #################################

; /nossh によって ssh 接続しないよう強制する。
sprintf2 msg "%s:%s /nossh /T=1" hostname _defPort
connect msg

; login
wait   UsernamePrompt
sendln username

wait   PasswordPrompt
send   password
sendln ''

return

:subArchive
; #################################
; # サブルーチン:subArchive
; #################################
; アカウント情報のアーカイブ

; 圧縮コマンドの生成
sprintf2 _ArchiveCmd "%s a -tzip -p%s %s %s" _7zip _filepassword _pwzip _pwdat

; 暗号化処理コマンドラインを実行する。
exec _ArchiveCmd 'hide' 1

; result (errorlevel) が 0 なら成功とみなして dat ファイルを削除する。
if result == 0 then
  filedelete _pwdat

else
  ; メッセージ生成
  sprintf2 msg 'パスワードファイルの圧縮に失敗しました。\n\n 対象ファイル: %s\n Exit Code: %d' _pwzip result
  sprintf2 title '圧縮失敗'
  strspecial msg
  messagebox msg title

  end

endif

; 元ファイルを削除する。
filedelete _pwdat
if result = 1 then
  sprintf2 msg 'ファイル %s が削除できませんでした。' _pwdat
  end

endif

return

備考

改版履歴
バージョン公開日付添付ファイル内容
第2版2019/7/28SelectAccess_v2.zip・Telnet 接続選択時に connet コマンドへ telnet 接続を強制するオプションを追記した。
・アカウント名は毎回入力するようにデフォルトを変更した。
・パスワード関係のファイル名がデバッグ時のものになっていたので修正した。
・Windows 登録情報削除までの待機時間を 30 秒 → 15 秒に調整した。
・エラー対象「.dat」ファイルがある場合の goto 先ラベルが無かったので追記した。
・コマンドライン版 7zip が存在しない場合のエラー処理を追加した。
初版2019/7/24SelectAccess.zip・初版を公開した。

*3 : マスターパスワードではありません。