資格情報マネージャ読み書きプログラムをNode.jsで作成する
VBA等のスクリプト系は、Windowsの資格情報マネージャに格納されてる情報を直接取得する事が出来ません。かといって、Web API等のアクセスに必要な情報を直書きしたり、そのままレジストリに書き込んで読み書きでは不安です。
そこで今回、Node.js + Keytar + nexeでexeを作成し、コマンドラインの標準出力でVBA側にパスワードを渡す手法を考えてみました。
※正直言って実用的じゃないので、素直に暗号化モジュール使って、暗号/複合を実装したほうがなんぼもマシだと思います
リンク
今回使用するモジュール
今回は、Node.jsにコマンドライン引数を渡して処理し、返り値をDOS窓の標準出力を取得する形で手に入れます。
ソースコード
Node.js側コード
"use strict"
//モジュールの読み込み
const fs = require('fs');
const keytar = require('keytar');
const commandLineArgs = require('command-line-args');
//コマンドラインオプションを構築
const optionDefinitions = [
{
name: 'userid',
alias: 'u',
type: String
},
{
name: 'setpass',
alias: 's',
type: String
},
{
name: 'getpass',
alias: 'g',
type: String
}
];
const args = commandLineArgs(optionDefinitions);
//引数に応じて処理を分岐
var userid = args.userid;
if(userid == undefined){
//User ID指定がないので処理を終了
return 0;
}
//サービス名を構築する
var servicename = "kintone_" + userid;
//-gオプションの値を取得する
var tempargs = args.getpass;
if(tempargs == undefined){
//getじゃないのでsetなのか判定
tempargs = args.setpass;
if(tempargs == undefined){
//オプション指定がないので処理を終了
return 0;
}else{
//パスワードセットの処理を実行
setPassword(servicename,userid,tempargs,function(ret){
console.log(ret);
return ret;
});
}
}else{
//パスワードゲットの処理を実行
getPassword(servicename,userid,function (ret){
console.log(ret);
return ret;
})
}
//パスワードを取得する処理
function getPassword(servicename,userid,callback){
const secret = keytar.getPassword(servicename,userid);
secret.then((result) => {
return result;
})
.then(function(data) {
callback(data);
return data;
})
}
//パスワードをセットする処理
function setPassword(servicename,userid,pass,callback){
//パスワードを保存する
keytar.setPassword(servicename,userid,pass);
//処理完了
callback(1);
return 1;
}
- optionDefinitionsにて、コマンドライン引数オプションの-sと-u、-gの場合の処理を用意しています。
- コマンドラインとして、node index.js -u ユーザID -s パスワードとすると、パスワードを資格情報マネージャにセットします。
- コマンドラインとして、node index.js -u ユーザID -g ユーザIDとすると、パスワードを資格情報マネージャからゲットします。
- -gの時の処理、-sの時の処理それぞれを条件分岐で作成します。
- setPasswordでkeytarを使ってパスワードをセットします。
- getPasswordでkeytarを使ってパスワードをゲットします。
- keytar自体、非同期で実行されるので、callbackやthenなどを利用して値を取得後に標準出力で出すようにコードを記述する必要があります。
- servicenameは、利用するウェブサービス等の名称と組み合わせる何か(例えばUser ID)で組み立てます。これを元に資格情報マネージャにセットしたり、取得したりします。
VBA側コード
Sub credmanexe()
'WSHの用意
Dim WSH, wExec, sCmd As String, Result As String
Set WSH = CreateObject("WScript.Shell")
//コマンドラインの組み立てと実行
sCmd = ThisWorkbook.Path & "\creden.exe -u ユーザID -g ユーザID"
Set wExec = WSH.Exec("%ComSpec% /c " & sCmd)
//ステータスを見てループ
Do While wExec.Status = 0
DoEvents
Loop
//標準出力内容を取得してメッセージボックスで表示
Result = wExec.StdOut.ReadAll
MsgBox Result
//終了処理
Set wExec = Nothing
Set WSH = Nothing
End Sub
- WSHを利用してexecにてコマンドラインを実行しています(今回はとりあえずパスワードの取得の部分だけ)
- StdOut.ReadAllにて標準出力(console.log())に出力された内容を取得しています。
- コマンドプロンプトの画面はexecの場合、非表示に出来ません。しかし、Runの場合今度は標準出力を取得できません。
- VBSを利用したコマンドプロンプト非表示のテクニックがあるので、こちらを利用すると尚良いでしょう。
- パスワード取得とパスワードセットの2つのルーチンに対して、今回のコードを組み込んでおきます。
単一実行ファイルを作成する
Node.js 18よりSingle executable applicationsという機能が装備され、標準で単独実行ファイルが作成できるようになりました。結果pkgはプロジェクト終了となっています。よって、以下のエントリーの単一実行ファイルを作成するを参考に、Node18以降はexeファイルを作成することが可能です。

