Administrative Credentials Record (管理者認証情報レコード): 空白のままでも構いません。
Pythonスクリプト
以下は、Cisco IOS XEのユーザー認証情報をローテーションする PAMスクリプトです。
'''Ciscoユーザーアカウントのパスワードローテーションスクリプトこのスクリプトで、指定されたCiscoユーザーのパスワードがローテーションされます。Cisco環境内でのユーザーパスワードの自動更新が容易になります。注: Pythonインタープリタへのパスにスペースが含まれている場合、スクリプトの実行が失敗します。これはLinuxのシバン行における既知の制限であり、スペースを含まないパスにPythonインタープリタへのシンボリックリンクを作成する必要があります。 例: sudo ln -s "/usr/local/bin/my python3.7" /usr/local/bin/pam_rotation_venv_python3'''import sysimport base64import jsonimport urllib3urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)'''デバッグのためにインストールされているパッケージを表示するオプションです。必要に応じてコメントを外して使用してください。import pkg_resourcesprint("# \n# Installed packages for debugging:")installed_packages = pkg_resources.working_setinstalled_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 requestsexceptImportError:print("# Error: The 'requests' package is not installed. Run 'pip install requests' to install it.")exit(1)defget_username_details(cisco_url,cisco_admin_username,cisco_admin_password,cisco_user_name):""" Verify the Cisco user. Args: - cisco_url (str): The host endpoint of the Cisco account to connect to. - cisco_admin_username (str): The username of the Cisco admin account. - cisco_admin_password (str): The password of the Cisco admin account. - cisco_user_name (str): The name of the Cisco user whose password needs to be rotated. Returns: - True if username found. """# ユーザー名APIエンドポイント用のリクエストURLを構築します。 request_url =f"{cisco_url}username/"# RESTCONFリクエストのヘッダーを設定し、送受信するYANGデータをJSON形式に指定します。 headers ={'Accept':'application/yang-data+json','Content-Type':'application/yang-data+json'}try:# Ciscoルーターに対してGETリクエストを送信し、ユーザー詳細を取得します。 response = requests.get(request_url, headers=headers, auth=(cisco_admin_username,cisco_admin_password), verify=False) response.raise_for_status() data = response.json()# レスポンスデータからユーザー名のリストを抽出します。 usernames = data["Cisco-IOS-XE-native:username"]# ユーザー名のリストを反復処理して、指定されたユーザーを探します。for user in usernames:if user["name"]==cisco_user_name:# 指定されたユーザー名が見つかった場合、True を返します。returnTrueexcept requests.exceptions.HTTPError as http_err:print(f"HTTP error occurred while fetching username details from Cisco router: {http_err}")exceptExceptionas err:print(f"An error occurred: {err}")returnFalsedefrotate(cisco_url,cisco_admin_username,cisco_admin_password,cisco_user_name,new_password):""" Rotate the password for a given Cisco user. Args: - cisco_url (str): The host endpoint of the Cisco account to connect to. - cisco_admin_username (str): The username of the Cisco admin account. - cisco_admin_password (str): The password of the Cisco admin account. - cisco_user_name (str): The name of the Cisco user whose password needs to be rotated. - new_password (str): The new password to be set for the Cisco user. Returns: - None """# 指定されたユーザーがCiscoルーターに存在するか確認するために、get_username_details 関数を呼び出します。 user =get_username_details(cisco_url, cisco_admin_username, cisco_admin_password, cisco_user_name)# ユーザーが存在しない場合、エラーメッセージを表示してプログラムを終了します。ifnot user:print(f"No user found with the username: {cisco_user_name}")exit(1)# RESTCONFリクエストのヘッダーを設定し、YANGデータをJSON形式で送受信することを指定します。 headers ={'Accept':'application/yang-data+json','Content-Type':'application/yang-data+json'}# ユーザーのパスワードを更新するためのPATCHリクエストのデータペイロードを作成します。 data ={"Cisco-IOS-XE-native:native":{"username": [{"name": cisco_user_name,"password":{"password": new_password}} ]}}try:# CiscoルーターにPATCHリクエストを送信して、ユーザーのパスワードを更新します。 response = requests.patch(cisco_url, headers=headers, auth=(cisco_admin_username,cisco_admin_password), data=json.dumps(data), verify=False) response.raise_for_status()print(f"Password updated successfully for user {cisco_user_name}")except requests.exceptions.HTTPError as http_err:print(f"HTTP error occurred while updating the password for the given user: {http_err}")exceptExceptionas err:print(f"An error occurred: {err}")defmain():""" Main function to rotate the password for a Cisco device user. Reads and decodes input parameters from stdin, including the authentication record details and the new password. Then, updates the password of the specified Cisco device user. """ record_title ='Cisco Authentication Record'#ユーザー名、パスワード、およびホストエンドポイントの詳細を含むレコードのタイトルと同じである必要があります。 api_access_token_record =None params =None# 標準入力(stdin)から入力パラメータを読み取り、デコードします。for base64_params in sys.stdin: params = json.loads(base64.b64decode(base64_params).decode())# PAMスクリプトセクションで「Rotation Credential」レコードとして渡されたJSON文字列をデコードして読み込みます。 records = json.loads(base64.b64decode(params.get('records')).decode())# 指定されたタイトルと一致するレコードを検索します。 api_access_token_record =next((record for record in records if record['title'].lower() == record_title.lower()), None)breakif api_access_token_record isNone:print(f"# Error: No Record with the access token found. Title: {record_title}")exit(1)# レコードから詳細情報を抽出します。# Ciscoデバイスのエンドポイントであるホスト名(HostName)です。 cisco_router_endpoint = api_access_token_record.get('host_endpoint')# Ciscoデバイスの管理者ユーザー名。 cisco_admin_username = api_access_token_record.get('login')# Ciscoデバイスの管理者パスワード。 cisco_admin_password = api_access_token_record.get('password')# パスワードをローテーションする必要があるCiscoデバイスのユーザー名。 cisco_user_name = params.get('user')# Ciscoデバイスのユーザーに設定する新しいパスワード。 new_password = params.get('newPassword')# 必要なすべてのフィールドが存在するか確認します。ifnotall([cisco_router_endpoint, cisco_admin_username, cisco_admin_password, cisco_user_name]):print("# Error: One or more required fields are missing in the access token record.")exit(1)# Cisco API URLを構築します。 cisco_url =f"https://{cisco_router_endpoint}/restconf/data/Cisco-IOS-XE-native:native/"# 指定されたCiscoデバイスユーザーのパスワードをローテーションします。rotate(cisco_url, cisco_admin_username, cisco_admin_password, cisco_user_name, new_password)if__name__=="__main__":main()