> For the complete documentation index, see [llms.txt](https://docs.keeper.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.keeper.io/keeperpam/jp/privileged-access-manager/password-rotation/rotation-use-cases/saas-account/okta-user.md).

# Oktaユーザー

![](/files/9ZVrpRuaVuArcWGbtWSZ)

## 概要 <a href="#overview" id="overview"></a>

本ページでは、Okta APIとKeeperゲートウェイのポストローテーションスクリプトを使用して、Oktaユーザーアカウントのパスワードをローテーションする手順を取り扱います。

組み込みのSaaSローテーションを利用する場合は、[SaaSプラグイン](/keeperpam/jp/privileged-access-manager/password-rotation/rotation-use-cases/saas-plugins.md)をご参照ください。

## 要件 <a href="#prerequisites" id="prerequisites"></a>

以下がすでに完了していることを前提としています。

* Keeperシークレットマネージャー[アプリケーション](/keeperpam/jp/privileged-access-manager/getting-started/applications.md)が作成済みであること
* 関連レコードを格納する共有フォルダが作成されていること
* PAM構成が設定済みで、ゲートウェイが稼働中であること
* Python環境に `okta` パッケージがインストールされていること (`pip install okta`)

## 1. Okta APIトークンの取得 <a href="#id-1-obtain-okta-api-token" id="id-1-obtain-okta-api-token"></a>

1. [Oktaの公式ドキュメント](https://developer.okta.com/docs/guides/create-an-api-token/main/)の手順に従ってAPIトークンを生成します。
2. Keeperボルトにレコードを作成し、APIトークンと組織URLを保存します。レコードタイプは任意ですが、本例では「ログイン」を使用します。
   * APIトークンを**パスワード**フィールドに保存
   * 組織のURLを**ウェブサイトアドレス**フィールドに保存
3. レコードタイトルは、スクリプト内の `okta_api_access_details_title` と一致させます (本例では `ROT5: Okta API Access Details`)。

![](/files/3YBDxYLhsfDJlMNkkSaK)

## 2. ローテーション対象ユーザーのPAMユーザーレコード作成 <a href="#id-2-set-up-rotation-record" id="id-2-set-up-rotation-record"></a>

ローテーション対象のOktaユーザー用にPAMユーザーレコードを作成します。

* **ログイン**にOktaユーザーのメールアドレスを設定
* **パスワード**に現在のパスワードを設定

{% hint style="info" %}
Okta SDKでは、現在のパスワードが有効な場合にのみパスワードをローテーションできます。パスワードが誤っている場合、ローテーションは失敗します。
{% endhint %}

## 3. ローテーション設定の構成 <a href="#id-3-configure-rotation-settings" id="id-3-configure-rotation-settings"></a>

**\[ローテーション設定]** で **\[セットアップ]** を開き、以下を設定します。

* **\[ローテーションプロファイル]:** **\[PAMスクリプトのみを実行する]**
* **\[ローテーションタイプ]:** 本例では**オンデマンド**
* **\[PAMリソース]:** ゲートウェイに対応するPAM構成
* **\[管理者認証情報レコード]:** 空欄のまま
* **\[アップデート]** で保存

![](/files/FoCOlKPc6EbGOUSNQZEP)

## 4. ポストローテーションスクリプトのアップロード <a href="#id-4-upload-the-post-rotation-script" id="id-4-upload-the-post-rotation-script"></a>

**\[PAMスクリプト]** で **\[PAMスクリプトを追加]** をクリックし、以下のスクリプトを添付します。

* **\[ローテーションクレデンシャル]** に、手順1で作成したOkta APIレコードを指定

## Pythonスクリプト <a href="#python-script" id="python-script"></a>

以下は、OktaユーザーのパスワードをローテーションするPAMスクリプトです。各行にコメントを付けています。

{% code overflow="wrap" %}

```python
#!/usr/local/bin/pam_rotation_venv_python3

# 注: Pythonインタープリタへのパスにスペースが含まれている場合、スクリプトは実行に失敗します。
#     これはLinuxのシバン行の既知の制限であり、スペースを含まないパスに
#     Pythonインタープリタへのシンボリックリンクを作成する必要があります。
#     例: sudo ln -s "/usr/local/bin/my python3.11" /usr/local/bin/pam_rotation_venv_python3

import asyncio
import sys
import base64
import json

# 注: Okta SDKでは、以前のパスワードが指定されている場合にのみパスワードのリセットが可能です。
#     処理が失敗した場合、このスクリプトでは古いパスワードに戻されません。
#     スクリプトを実行する前に、古いパスワードが正しいことを確認してください。
#     このスクリプトは一例であり、Keeper Securityのサポート対象外です。

# Pythonのバージョンを表示
print(f"# Python version: {sys.version}")

# インストールされているパッケージを表示します。
# 以下の行のコメントを解除して環境をチェックし、必要なパッケージがインストールされていることを確認します。

# import pkg_resources
# print("# \n# Print installed packages for debugging purposes:")
# 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}")

# Oktaモジュールをインポート
try:
    import okta
    from okta.client import Client as OktaClient
except ImportError:
    print("# Error: Okta client package is not installed. Run 'pip install okta' to install.")
    exit(1)


# レコード内のタイトルでパスワードを特定する関数
def find_password_by_title(records, target_title):
    """Search for a password by its title in the given records."""
    for record in records:
        if record['title'] == target_title:
            return record['password']
    return None  # Return None if no matching record is found


# 変数を初期化
okta_api_access_details_title = 'ROT5: Okta API Access Details'
okta_api_access_details_record = None

# stdinから入力パラメータを読み取り、デコードします
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}")

    # レコードをデコードしてロード
    records = json.loads(base64.b64decode(params.get('records')).decode())

    # Okta APIアクセス詳細レコードを特定
    okta_api_access_details_record = next(
        (record for record in records if record['title'] == okta_api_access_details_title), None)
    break

# Okta APIクレデンシャルが見つからない場合は終了
if okta_api_access_details_record is None:
    print(f"# Error: No Okta API Credentials record found with title: {okta_api_access_details_title}")
    exit(1)

# Okta設定の詳細を抽出
okta_org_url = okta_api_access_details_record.get('url')
okta_org_token = okta_api_access_details_record.get('password')
old_password = params.get('oldPassword')
new_password = params.get('newPassword')

# Oktaクライアントを初期化
config = {
    "orgUrl": okta_org_url,
    "token": okta_org_token
}
okta_client = OktaClient(config)


async def get_all_users():
    """Fetch all Okta users."""
    users, _, err = await okta_client.list_users()
    if err:
        print(f"# Error: {err}")
    return users


async def get_okta_user_by_email(email):
    """Fetch an Okta user by their email."""
    print(f"# Fetching all Okta users...")
    users = await get_all_users()

    print(f"# Searching for user with email: {email}")
    found_user = next((user for user in users if user.profile.email == email), None)

    return found_user


async def rotate(user_id_to_rotate, old_password, new_password):
    """Rotate the password for a given Okta user."""

    change_pwd_request = {
        "oldPassword": old_password,
        "newPassword": new_password,
    }

    result, _, err = await okta_client.change_password(user_id_to_rotate, change_pwd_request)
    if err:
        print(f"# Error: {err}")
    else:
        print(f"# Password changed successfully for user: {user_id_to_rotate}")


async def main():
    """Main function to execute the password rotation."""
    user_email = params.get('user')

    print(f"# Fetching Okta user by email: {user_email}. This is required to get the user's Okta ID.")
    print(f"# If user id is present then there is no need to fetch the user by email and instead just use the user id.")
    user_from_okta = await get_okta_user_by_email(user_email)

    print(f"# Getting user id from Okta user")
    user_from_okta_id = user_from_okta.id if user_from_okta else None

    print(f"# Rotating password for user: {user_from_okta_id}")
    if user_from_okta_id:
        await rotate(user_from_okta_id, old_password, new_password)
    else:
        print(f"# Error: User {user_email} not found in Okta.")
        print("# Please ensure that the user exists in Okta and try again.")


if __name__ == '__main__':
    print("# Starting the main async function...")
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
```

{% endcode %}

## 5. Python実行環境の準備 <a href="#id-5-python-environment-setup" id="id-5-python-environment-setup"></a>

Keeperゲートウェイが動作している環境で、Pythonと依存パッケージがインストールされていることを確認します。仮想環境を使用する場合は、スクリプト先頭のシバン行を設定します。

{% hint style="info" %}
シバン行のパスにスペースを含めないでください。スペースがある場合は、スペースを含まないシンボリックリンクを作成します。

Linuxでの例:

`sudo ln -s "/Users/john/PAM Rotation Example/.venv/bin/python3" /usr/local/bin/pam_rotation_venv_python3`
{% endhint %}

**\[追加認証情報]** で手順1のOkta APIレコードを選択し、**\[コマンドプレフィックス付きで実行]** を有効にしてPython実行ファイルのフルパスを指定します。Docker経由のゲートウェイでは通常 `/usr/local/bin/python3` です。

## 6. 構成の保存とローテーションの実行 <a href="#id-6-save-and-run-rotation" id="id-6-save-and-run-rotation"></a>

PAMユーザーレコードで **\[保存]** をクリックします。設定後、**\[PAMスクリプトのみを実行]** でオンデマンドローテーションを実行できます。

## Bashスクリプト版 <a href="#bash-script-version" id="bash-script-version"></a>

以下のBashスクリプトは、Okta REST APIを直接呼び出す代替例です。`jq` が必要です。

{% code overflow="wrap" %}

```bash
#!/usr/bin/env bash

# 注: Oktaでは、以前のパスワードがある場合にのみパスワードをリセットできます。
#    この操作が失敗した場合、このスクリプトで古いパスワードには戻りません。
#    スクリプトを実行する前に、古いパスワードが正しいことを確認してください。
#    このスクリプトは例であり、Keeper Securityのサポート対象外です。

# 以下のように実行します。
# history -c && echo "BASE64STRING==" | /path/to/script.sh

# 以下がないと、スクリプト内で何かが失敗しても、スクリプトが成功を報告する可能性があります。
set -o pipefail -e

IFS= read -r params
json=$(echo "$params" | base64 -d)

# JSONを解析するための組み込みのパーサーはありません。
# JSONを解析するには、jqやfxのようなツールが必要です。
$(echo "$json" | jq -r 'keys[] as $k | "export \($k)=\(.[$k])"')

# Okta APIトークンと組織のURLを設定
recordJson=$(echo "$records" | base64 -d)
OKTA_API_RECORD="Okta API Access Details"
OKTA_API_TOKEN=$(echo "$recordJson" | jq -r ".[] | select(.title == \"$OKTA_API_RECORD\").password")
OKTA_ORG_URL=$(echo "$recordJson" | jq -r ".[] | select(.title == \"$OKTA_API_RECORD\").url")

# ユーザーのIDと新しいパスワードを設定
USER_ID="$user"
OLD_PASSWORD="$oldPassword"
NEW_PASSWORD="$newPassword"

curl -v -X POST \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "Authorization: SSWS "$OKTA_API_TOKEN"" \
-d '{
    "oldPassword": "'"$OLD_PASSWORD"'",
    "newPassword": "'"$NEW_PASSWORD"'"
}' "$OKTA_ORG_URL/api/v1/users/$USER_ID/credentials/change_password"
```

{% endcode %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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/okta-user.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.
