MAGAZINE
ルーターマガジン
コマンドライン上で2要素認証のコードを取得しログインを自動化する

はじめに
近年、国内でも不正アクセスによる事件が相次ぎ、私たちが利用している多くのサービスで「二段階認証」の導入がほぼ必須となっています。 その中でも代表的なのが、Google Authenticatorを使ったワンタイムパスワード方式です。
本記事では、そのワンタイムパスワードをコマンドラインから取得し、最終的に自動化するまでの手順をまとめて紹介します。
Google Authenticator
二段階認証を提供するためのモバイルアプリケーションは複数ありますが、今回はGoogle Authenticatorを利用します。
登録したアカウントに紐づくワンタイムパスワードを生成し、それを30秒ごとに更新する機能を持っています。
複数のアカウントを同時に管理することができ、新規のアカウントを追加する際には、QRコードをスキャンすることで簡単にセットアップできます。
さらに以下のようなChrome拡張を用いることで、登録したアカウントのワンタイムパスワードをブラウザ上で表示することが可能です。
https://chromewebstore.google.com/detail/authenticator/bhghoamapcdpbohphigoooaddinpkbai?hl=ja
ワンタイムパスワードをCLIから取得する方法
まずは先程のChrome拡張アプリを用いて確認していたワンタイムパスワードをCLIから取得できるようにします。
手順は以下の通りです。
- oathtoolをインストール
- sudo apt install oathtool
- Google Authenticatorからシークレットキーを入手(方法は後述)
- 例:0123456789ABCDEFGHIJKLMNOPQRSTUV
- コマンドライン上で oathtool --totp -b “SECRET_KEY” を実行
ここで、Google Authenticatorからシークレットキーを入手する手順は以下の通りです。
- Chrome拡張のAuthenticatorを開き、左上の歯車アイコンからメニューを開く
- 事前にAuthenticatorにログインに使うアカウントを登録しておく
- メニューから「バックアップ」を選択
- 「バックアップファイルのダウンロード」を選択しテキストファイルをダウンロードする
- ダウンロードしたauthenticator.txtの中身を確認する。
secretパラメータの値がシークレットキーとなっている。
Tableauへのログインを自動化
今回は「Tableau」を例に自動化をしてみます。
サンプルプログラム(tableau_login.rb)
以下のコマンドで実行してください。rubyファイルと.envファイルが同じ階層にあることを確認してください。
require 'chrome_remote'
require 'dotenv'
# 2段階認証コードをCLIから取得
def fetch_otp(secret_key)
otp = `oathtool --totp -b #{secret_key}`.strip
puts "One-time password: #{otp}"
otp
end
# Chrome のリモートデバッグポートを指定してクライアントを作成
def launch_chrome
# 事前に何らかのuser-data-dirを指定してChromeを起動しておき、初期設定を済ませておく必要がある
IO.popen("google-chrome --remote-debugging-port=9222 --user-data-dir=./tmp/chrome_temp_dir")
# Chromeが起動するまで待機
sleep 2 until TCPSocket.new('localhost', 9222) rescue sleep 1
end
# クライアントを作成、自動操作を有効化
def create_client
@client = ChromeRemote.client
@client.send_cmd('Runtime.enable')
@client.send_cmd('Page.enable')
end
# 必要な要素がロードされるまで待機する
def wait_for_page_load(client, selectors)
expression = selectors.map { |selector| "!!document.querySelector('#{selector}')" }.join(' && ')
loop do
result = client.send_cmd('Runtime.evaluate', expression: expression)
break if result['result']['value']
sleep 0.5
end
end
# ログインページの操作
def manipulate_login_page(email)
@client.send_cmd('Page.navigate', url: 'https://sso.online.tableau.com/public/login')
wait_for_page_load(@client, ['#email', '#login-submit'])
@client.send_cmd('Runtime.evaluate', expression: <<-JS)
document.querySelector('#email').value = '#{email}';
document.querySelector('#login-submit').click();
JS
end
# サイトURIの入力ページの操作
def manipulate_site_uri_page(site_uri)
wait_for_page_load(@client, ['#site-uri', '#verify-button'])
@client.send_cmd('Runtime.evaluate', expression: <<-JS)
document.querySelector('#site-uri').value = '#{site_uri}';
document.querySelector('#site-uri').dispatchEvent(new Event('input', { bubbles: true }));
document.querySelector('#verify-button').disabled = false;
document.querySelector('#verify-button').click();
JS
end
# パスワードの入力ページの操作
def manipulate_password_page(password)
wait_for_page_load(@client, ['#password', '#signInButton'])
@client.send_cmd('Runtime.evaluate', expression: <<-JS)
document.querySelector('#password').value = '#{password}';
document.querySelector('#signInButton').click();
JS
end
# 2段階認証コードの入力ページを操作
def manipulate_otp_page(secret_key)
wait_for_page_load(@client, ['#root'])
otp = fetch_otp(secret_key)
@client.send_cmd('Runtime.evaluate', expression: <<-JS)
document.querySelector('#root').querySelector('#input-9').value = '#{otp}';
document.querySelector('#root').querySelector('button.slds-button_brand[type="submit"]').click();
JS
end
# エントリーポイント
if __FILE__ == $PROGRAM_NAME
# .envファイルから環境変数をロード
Dotenv.load('.env')
launch_chrome
create_client
manipulate_login_page(ENV['TABLEAU_EMAIL'])
manipulate_site_uri_page(ENV['TABLEAU_SITE_URI'])
manipulate_password_page(ENV['TABLEAU_PASSWORD'])
manipulate_otp_page(ENV['TABLEAU_2FA_SECRET_KEY'])
puts "Login process completed."
end
chrome_remoteを用いてGoogle Chromeを自動操縦し、ログインプロセスを自動化するという流れです。
実行の方法を説明します。まず、以下を参考にしてrubyプログラムと同じ階層に.envファイルを用意してください。
TABLEAU_2FA_SECRET_KEY = '0123456789ABCDEFGHIJKLMNPQRSTUV'
TABLEAU_EMAIL = 'sample@sample.com'
TABLEAU_PASSWORD = 'samplePassword'
TABLEAU_SITE_URI = 'sampleSite'
各変数の意味は以下の通りです。皆様の環境に合わせて適宜設定してください。
- TABLEAU_2FA_SECRET_KEY:シークレットキー
- TABLEAU_EMAIL:ログインに用いるEメールアドレス
- TABLEAU_PASSWORD:ログインに用いるパスワード
- TABLEAU_SITE_URI:Tableau CloudのサイトURI
Gemfile
上記のRubyプログラムでは外部ライブラリを利用しています。
そのため、以下のようなGemfileを用意してください。
source 'https://rubygems.org'
gem 'chrome_remote'
gem 'dotenv'
Rubyプログラムの実行前に以下のコマンドを実行してください。
bundle install
実行方法
用意ができたら、以下のコマンドでコードを実行してください。実行が終わると、Tableauへのログインが完了した状態となります。
bundle exec ruby tableau_login.rb
まとめ
今回はコマンドライン上でワンタイムパスワードを取得し、ログインを自動化するサンプルをご紹介しました。 弊社では、このような複雑なログイン作業も自動化することが可能です。 自動化でお困りの際はぜひご相談ください。
CONTACT
お問い合わせ・ご依頼はこちらから