[script]1password CLIでパスワード出力スクリプト作ってみた

目次

使用用途

このスクリプトは 1Password に保存された認証情報を取得し、サーバーへのログインを簡単にする ためのものです。

  • config.json に登録されたサーバー情報を元に、ユーザーがログイン先を選択。
  • 1Password から認証情報を取得し、クリップボードにコピー
  • そのままサーバーへ SSH 接続 したり、Web ログインなどに利用可能。

使用環境

  • MacOS
  • terminal
  • zsh

事前準備

1Password CLIをインストール

brew install 1password-cli

1Password CLIバージョン確認

op --version

1Passwordにサインイン

eval $(op signin)

このコマンドを実行すると、対話的に アカウント情報の入力(サブドメイン、メールアドレス、シークレットキー、マスターパスワード)が求められます。

1Passwordアカウント情報

op account get

スクリプト

実装方法

configファイルと実行スクリプトは同階層に配置すこと
実行スクリプト(get_op_password.sh)
#!/bin/zsh

# JSONファイルの指定(ローカルに配置)
JSON_FILE="config.json"

# 1Password のサインイン状態を確認
echo "\033[0;34m[INFO]\033[0;39m 1Password のセッションを確認しています..."
if ! op account get &>/dev/null; then
    echo "\033[0;31m[ERROR]\033[0;39m 1Password のセッションが無効または破損しています。"
    echo "\033[0;33m[ACTION]\033[0;39m 以下のコマンドを実行してサインインしてください:"
    echo "\033[0;32meval \$(op signin)\033[0;39m"
    exit 1
fi

# システム選択
SYSTEM_LIST=$(jq -r '.[0] | keys_unsorted | to_entries | map("\(.key + 1)) \(.value)") | .[]' "$JSON_FILE")

echo "\n\033[0;32mシステム選択メニュー:\033[0;39m"
echo "$SYSTEM_LIST"
echo "\033[0;31m0) 終了\033[0;39m"
read -p $'\033[0;36mシステムを選択してください > \033[0;39m' SYSTEM_CHOICE

if [ "$SYSTEM_CHOICE" -eq 0 ]; then
    echo "\033[0;34m[INFO]\033[0;39m プログラムを終了します。"
    exit 0
fi

# システム名の取得
SYSTEM_NAME=$(jq -r --argjson index "$((SYSTEM_CHOICE - 1))" '.[0] | keys_unsorted | .[$index]' "$JSON_FILE")

# 環境選択メニューの表示
ENV_LIST=$(jq -r --arg system "$SYSTEM_NAME" '.[0][$system] | keys_unsorted | to_entries | map("\(.key + 1)) \(.value)") | .[]' "$JSON_FILE")

echo "\n\033[0;32m${SYSTEM_NAME} 環境選択メニュー:\033[0;39m"
echo "$ENV_LIST"
echo "\033[0;31m0) 戻る\033[0;39m"
read -p "環境を選択してください > " ENV_CHOICE

if [ "$ENV_CHOICE" -eq 0 ]; then
    exec $0
fi

# 環境名の取得
ENV_NAME=$(jq -r --arg system "$SYSTEM_NAME" --argjson index "$((ENV_CHOICE - 1))" '.[0][$system] | keys_unsorted | .[$index]' "$JSON_FILE")

# 利用可能なカテゴリーを取得
echo "\n\033[0;32m操作対象を選択してください:\033[0;39m"
CATEGORY_LIST=$(jq -r --arg system "$SYSTEM_NAME" --arg env "$ENV_NAME" '.[0][$system][$env] | keys_unsorted | to_entries | map("\(.key + 1)) \(.value)") | .[]' "$JSON_FILE")

echo "$CATEGORY_LIST"
echo "\033[0;31m0) 戻る\033[0;39m"
read -p "選択 > " CATEGORY_CHOICE

if [ "$CATEGORY_CHOICE" -eq 0 ]; then
    exec $0
fi

CATEGORY_NAME=$(jq -r --arg system "$SYSTEM_NAME" --arg env "$ENV_NAME" --argjson index "$((CATEGORY_CHOICE - 1))" '.[0][$system][$env] | keys_unsorted | .[$index]' "$JSON_FILE")

# 選択したリストの取得
TARGET_LIST=$(jq -r --arg system "$SYSTEM_NAME" --arg env "$ENV_NAME" --arg category "$CATEGORY_NAME" '.[0][$system][$env][$category] | to_entries | map("\(.key + 1)) IP: \(.value.ip), パスワード名: \(.value.pass_name)") | .[]' "$JSON_FILE")

echo "\n\033[0;32m${SYSTEM_NAME} - ${ENV_NAME} の $CATEGORY_NAME 選択:\033[0;39m"
echo "$TARGET_LIST"
echo "\033[0;31m0) 戻る\033[0;39m"
read -p "対象を選択してください > " INSTANCE_CHOICE

if [ "$INSTANCE_CHOICE" -eq 0 ]; then
    exec $0
fi

# 選択した情報を取得
SELECTED_IP=$(jq -r --arg system "$SYSTEM_NAME" --arg env "$ENV_NAME" --arg category "$CATEGORY_NAME" --argjson index "$((INSTANCE_CHOICE - 1))" '.[0][$system][$env][$category][$index].ip' "$JSON_FILE")
ITEM_NAME=$(jq -r --arg system "$SYSTEM_NAME" --arg env "$ENV_NAME" --arg category "$CATEGORY_NAME" --argjson index "$((INSTANCE_CHOICE - 1))" '.[0][$system][$env][$category][$index].pass_name' "$JSON_FILE")

# 認証情報の取得
USERNAME=$(op item get "$ITEM_NAME" --fields username --reveal 2>/dev/null)
PASSWORD=$(op item get "$ITEM_NAME" --fields password --reveal 2>/dev/null)

# gatewayの取得
GATEWAY_TYPE=$(jq -r --arg system "$SYSTEM_NAME" --arg env "$ENV_NAME" '.[0][$system][$env].gateway' "$JSON_FILE")

if [ "$GATEWAY_TYPE" = "null" ] || [ -z "$GATEWAY_TYPE" ]; then
    GATEWAY_TYPE=0
fi

if [ "$GATEWAY_TYPE" -eq 1 ]; then
    GATEWAY_IP=$DMMGW
elif [ "$GATEWAY_TYPE" -eq 2 ]; then
    GATEWAY_IP=$VDIDBGW
else
    GATEWAY_IP=""
fi

# 選択結果の表示
echo "\n\033[0;32m選択されたIP: $SELECTED_IP\033[0;39m"
echo "\033[0;32m1Passwordアイテム名: $ITEM_NAME\033[0;39m"
echo "\033[0;32m取得したユーザー名: $USERNAME\033[0;39m"
echo "\033[0;32m取得したパスワード: $PASSWORD\033[0;39m"

# クリップボードにコピー(macOSとLinuxの両方に対応)
CLIPBOARD_CMD=""
if command -v pbcopy &>/dev/null; then
    CLIPBOARD_CMD="pbcopy"
elif command -v xclip &>/dev/null; then
    CLIPBOARD_CMD="xclip -selection clipboard"
elif command -v xsel &>/dev/null; then
    CLIPBOARD_CMD="xsel --clipboard --input"
fi

if [ -n "$CLIPBOARD_CMD" ]; then
    echo "$USERNAME" | $CLIPBOARD_CMD
    echo "\033[0;32mユーザー名をクリップボードにコピーしました。\033[0;39m"
    sleep 1  # 少し待ってからパスワードをコピー
    echo "$PASSWORD" | $CLIPBOARD_CMD
    echo "\033[0;32mパスワードをクリップボードにコピーしました。\033[0;39m"
else
    echo "\033[0;31mクリップボードのコマンドが見つかりませんでした。手動でコピーしてください。\033[0;39m"
fi
設定ファイル(config.json)
[
  {
    "ProjectA": {
      "production": {
        "web": [
          {
            "ip": "127.0.0.1",
            "pass_name": "hogehoge"
          },
          {
            "ip": "127.0.0.1",
            "pass_name": "piyopiyo"
          }
        ],
        "db": [
          {
            "ip": "127.0.0.1",
            "pass_name": "hogehoge"
          },
          {
            "ip": "127.0.0.1",
            "pass_name": "hugahuga"
          }
        ]
      },
      "staging": {
        "web+db": [
          {
            "ip": "127.0.0.1",
            "pass_name": "hogehoge"
          },
          {
            "ip": "127.0.0.1",
            "pass_name": "hugahuga"
          }
        ]
      }
    },
    "ProjectB": {
      "production": {
        "web": [
          {
            "ip": "127.0.0.1",
            "pass_name": "hogehoge"
          },
          {
            "ip": "127.0.0.1",
            "pass_name": "piyopiyo"
          }
        ],
        "db": [
          {
            "ip": "127.0.0.1",
            "pass_name": "hogehoge"
          },
          {
            "ip": "127.0.0.1",
            "pass_name": "hugahuga"
          }
        ]
      },
      "staging": {
        "web+db": [
          {
            "ip": "127.0.0.1",
            "pass_name": "hogehoge"
          },
          {
            "ip": "127.0.0.1",
            "pass_name": "hugahuga"
          }
        ]
      }
    }
  }
]

スクリプトの流れ

1. 1Password のセッション確認

op account get を実行して、1Password のセッションが有効かをチェック。
無効な場合、eval $(op signin) を実行するように指示して終了。

2. JSON ファイル(config.json)の読み込み

jq コマンドを使い、config.json から システムの一覧 を取得。
ユーザーにシステムを選択させる。

3. 環境の選択

ユーザーが選択したシステムに属する環境の一覧を取得。
ユーザーに環境を選択させる。

4. 操作対象(カテゴリー)の選択

ユーザーが選択したシステムと環境に属するカテゴリーの一覧を取得。
ユーザーにカテゴリーを選択させる。

5. ターゲット(接続先サーバー)の選択

ユーザーが選択したカテゴリーに属するサーバーの一覧を取得。
サーバーごとに、IPアドレス と 1Password 上のアイテム名 を表示。
ユーザーが接続したいサーバーを選択。

6. 1Password から認証情報を取得

op item get “$ITEM_NAME” –fields username –reveal
op item get “$ITEM_NAME” –fields password –reveal
で username と password を取得。

7. ゲートウェイの設定

config.json から gateway の設定を取得し、必要ならば DMMGW や VDIDBGW を適用。

8. 取得した情報を表示

選択した IPアドレス
1Password 上の アイテム名
取得した ユーザー名
取得した パスワード

9. クリップボードに認証情報をコピー

pbcopy, xclip, xsel のいずれかを利用して クリップボードにユーザー名とパスワードをコピー する。
macOS や Linux での使用を考慮。

この記事を書いた人

目次