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

<figure><img src="/files/xXEQd1xCCB2My3Y0KFy1" alt=""><figcaption></figcaption></figure>

## 概要

本ページでは、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実行環境の準備 <a href="#step-5-python-environment-setup" id="step-5-python-environment-setup"></a>

* Keeperゲートウェイが動作している環境で、Python環境と依存パッケージがインストールされていることを確認
* 仮想環境を使用する場合は、スクリプト冒頭にshebang行を追加
* 注意: shebang行にスペースがあると動作しないため、スペースなしのシンボリックリンクを作成してください。以下はLinuxでのシンボリックリンク作成の例です。

  <pre class="language-bash" data-overflow="wrap"><code class="lang-bash">sudo ln -s "/Users/john/PAM Rotation Example/.venv/bin/python3" /usr/local/bin/pam_rotation_venv_python3
  </code></pre>

### Pythonスクリプトについて

このPythonスクリプトは、ベストプラクティスに従って作成されており、以下の処理を行います。

* 必要なモジュールのインポート
* 変数の初期化
* 任意のREST APIを呼び出してパスワード変更を実行するローテーション関数の定義

```python
#!/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}")

```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.keeper.io/keeperpam/jp/privileged-access-manager/password-rotation/rotation-use-cases/saas-account/rotate-credential-via-rest-api.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
