REST APIを使用した認証情報のローテーション

概要
本ページでは、KeeperPAMのローテーションオプション「PAMスクリプトのみ実行」を使用して、REST APIを通じたパスワードローテーションを設定するための一般的な手順について取り扱います。この設定は、PAMユーザーレコードのローテーション設定において、メインのローテーション方法をスキップし、ボルトに添付されたスクリプト (ポストローテーションスクリプト) のみを直接実行させるものです。
本ページの最後にはPythonスクリプトのサンプルが含まれます。
要件
KSMアプリケーション: Keeperシークレットマネージャー (KSM) のアプリケーションが設定済みであること
共有フォルダ: 関連するレコードを格納するための共有フォルダが作成されていること
PAM構成: PAM構成が設定済みで、対応するゲートウェイが稼働中であること
REST APIトークン: 任意のAPIと連携するために必要なアクセストークンを取得していること
手順 1: REST APIトークンの取得
対象のアプリケーションまたはサービスで、APIトークンを生成します
Keeperボルトにレコードを作成し、このトークンを保存します
レコードタイプは「ログイン」を使用 (任意のタイプでも可)
APIトークンは「パスワード」欄に保存
組織のURLは「ウェブサイトアドレス」欄に入力
レコード名は 「API Access Details」 に設定 (スクリプト内で参照します)
手順 2: ローテーション対象ユーザーのPAMユーザーレコード作成
新たにPAMユーザーレコードを作成し、対象ユーザーの情報を保存します
ユーザー名にはログインIDを入力
パスワード欄には現在のパスワードを設定 (エンドポイント仕様による)
手順 3: PAMスクリプトの追加
以下のPythonスクリプトをレコードに添付します (スクリプト内には各行の解説付き)
スクリプト内で使用する「認証情報レコード」として、手順 1で作成した「API Access Details」レコードを指定
PAMユーザーレコードにカスタムテキストフィールド「NOOP」を追加し、値を
True
に設定 (NOOP=スクリプトのみ実行)
手順 4: パスワードローテーション設定
ローテーションタイプ: 「オンデマンド」を選択 (例として)
パスワードの複雑さ: 特に要件がなければデフォルトのまま
ローテーション設定: 先に作成したPAM構成を指定
管理者認証情報レコード: 空欄のままでOK
手順 5: Python実行環境の準備
Keeperゲートウェイが動作している環境で、Python環境と依存パッケージがインストールされていることを確認
仮想環境を使用する場合は、スクリプト冒頭にshebang行を追加
注意: shebang行にスペースがあると動作しないため、スペースなしのシンボリックリンクを作成してください。以下はLinuxでのシンボリックリンク作成の例です。
sudo ln -s "/Users/john/PAM Rotation Example/.venv/bin/python3" /usr/local/bin/pam_rotation_venv_python3
Pythonスクリプトについて
このPythonスクリプトは、ベストプラクティスに従って作成されており、以下の処理を行います。
必要なモジュールのインポート
変数の初期化
任意のREST APIを呼び出してパスワード変更を実行するローテーション関数の定義
#!/usr/local/bin/pam_rotation_venv_python3
# 注意: Pythonインタープリタへのパスにスペースが含まれている場合、このスクリプトは実行できません。
# これはLinuxにおけるshebang行の既知の制限であり、スペースを含まないパスに
# Pythonインタープリタへのシンボリックリンクを作成する必要があります。
# 例: sudo ln -s "/usr/local/bin/my python3.7" /usr/local/bin/pam_rotation_venv_python3
# 注意: このスクリプトは、REST APIを使用したパスワードローテーションのデモです。
# 実際のAPIを呼び出すものではありません。ご自身のAPIに合わせてスクリプトを修正してください。
import asyncio
import sys
import base64
import json
# デバッグ用にPythonのバージョンを表示
print(f"# Python version: {sys.version}")
# デバッグ用にインストール済みパッケージを表示(必要に応じてコメントを外してください)
# import pkg_resources
# print("# \n# Installed packages for debugging:")
# installed_packages = pkg_resources.working_set
# installed_packages_list = sorted(["%s==%s" % (i.key, i.version) for i in installed_packages])
# for m in installed_packages_list:
# print(f" {m}")
# requestsライブラリをインポート
try:
import requests
except ImportError:
# 'requests'パッケージがインストールされていない場合のエラーメッセージ
print("# Error: The 'requests' package is not installed. Run 'pip install requests' to install it.")
exit(1)
# 変数の初期化
api_access_token_title = 'Record with Access Token'
api_access_token_record = None
params = None
# 標準入力から渡されたパラメータを読み取り、デコード
for base64_params in sys.stdin:
params = json.loads(base64.b64decode(base64_params).decode())
# デバッグ用に利用可能なパラメータを表示(必要に応じてコメントを外してください)
# print(f"# \n# Available params for the script:")
# for key, value in params.items():
# print(f"# {key}={value}")
# PAMスクリプトの「ローテーションクレデンシャル」レコードとして渡された
# JSON文字列形式のレコード情報をデコードして読み込む
records = json.loads(base64.b64decode(params.get('records')).decode())
# タイトルからアクセストークンを含むレコードを探す
api_access_token_record = next(
(record for record in records if record['title'] == api_access_token_title), None)
break
if api_access_token_record is None:
# アクセストークンを含むレコードが見つからない場合のエラー
print(f"# Error: No Record with the access token found. Title: {api_access_token_title}")
exit(1)
# レコードから詳細情報を抽出
rest_api_service_url = api_access_token_record.get('url')
service_access_token = api_access_token_record.get('password')
# old_password = params.get('oldPassword') # 以前のパスワードを使用したい場合はこちらを使用
new_password = params.get('newPassword')
user_email = params.get('user') # パスワードをローテーションする対象ユーザーのメールアドレス
def rotate(user_email, new_password):
"""
指定されたユーザーのパスワードをローテーションします。
引数:
- user_email (str): パスワードをローテーションする対象ユーザーのメールアドレス
- new_password (str): 新しいパスワード
戻り値:
- dict: APIからのレスポンス
"""
# リクエストのヘッダー
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {service_access_token}"
}
# リクエストのペイロードを準備
request_payload = {
"userEmail": user_email,
"newPassword": new_password,
}
# APIにPOSTリクエストを送信
response = requests.post(url=rest_api_service_url, headers=headers, data=json.dumps(request_payload))
# リクエストが成功したかを確認
if response.status_code == 201:
return response.json()
else:
response.raise_for_status()
if __name__ == '__main__':
"""パスワードローテーションを実行するメイン関数"""
response = rotate(user_email, new_password)
# デバッグ用にAPIのレスポンスを表示
print(f"# \n# Response from the API:")
print(f"# {response}")
最終更新