Aurora PostgreSQL 互換 DB クラスターへの接続におけるパスワードの複雑さと有効期限を管理する方法を教えてください。
Amazon Aurora PostgreSQL 互換エディションデータベース (DB) クラスターへの接続におけるパスワードの複雑さと有効期限を管理したいと考えています。
簡単な説明
Aurora PostgreSQL 互換 DB クラスターのパスワードを管理するには、以下の方法を使用します。
- Trusted Language Extension (TLE) を使用してパスワードチェックフックを作成する。
- 制限されたパスワード管理機能を有効にする。
- AWS Identity and Access Management (IAM) データベース認証を使用する。
- IAM ユーザー用のカスタムパスワードポリシーを作成する。
- AWS Secrets Manager を使用する。
解決策
TLE を使用してパスワードチェックフックを利用する
TLE を使用してパスワードチェックフックを利用するには、まず Aurora PostgreSQL 互換 DB クラスターに TLE をセットアップする必要があります。次に、パスワードチェックフックを作成します。
注: フックの名前を付けるときに user-password-check-rules は使用できません。
パスワードチェックフックのコード例:
SELECT pgtle.install_extension( 'user-password-check-rules', '1.0', 'Do not let users use the 10 most commonly used passwords', $_pgtle_$ CREATE SCHEMA password_check; REVOKE ALL ON SCHEMA password_check FROM PUBLIC; GRANT USAGE ON SCHEMA password_check TO PUBLIC; -- Create table for bad passwords CREATE TABLE password_check.bad_passwords (plaintext) AS VALUES ('123456'), ('password'), ('12345678'), ('qwerty'), ('123456789'), ('12345'), ('1234'), ('111111'), ('1234567'), ('dragon'); -- Create table for tracking user password changes CREATE TABLE password_check.usertime ( user_name text PRIMARY KEY, lasttime timestamp ); CREATE UNIQUE INDEX ON password_check.bad_passwords (plaintext); CREATE FUNCTION password_check.passcheck_hook(username text, password text, password_type pgtle.password_types, valid_until timestamptz, valid_null boolean) RETURNS void AS $$ DECLARE invalid bool := false; userexists bool; last_password_change timestamp; BEGIN -- Check if user already exists SELECT EXISTS (SELECT user_name FROM password_check.usertime WHERE user_name = username) INTO userexists; -- If user exists, check password age IF (userexists) THEN SELECT lasttime INTO last_password_change FROM password_check.usertime WHERE user_name = username; -- Check if password is older than 90 days IF (CURRENT_TIMESTAMP - last_password_change) > INTERVAL '90 days' THEN RAISE EXCEPTION 'Password has expired. It must be changed every 90 days. Last change was on %', last_password_change; END IF; -- Update timestamp for new password change UPDATE password_check.usertime SET lasttime = CURRENT_TIMESTAMP WHERE user_name = username; ELSE -- First time user, add to tracking table INSERT INTO password_check.usertime VALUES(username, CURRENT_TIMESTAMP); END IF; -- Existing password length check IF length(password) < 8 THEN RAISE EXCEPTION 'Password must be at least 8 characters long.'; END IF; -- Existing common password check IF password_type = 'PASSWORD_TYPE_MD5' THEN SELECT EXISTS( SELECT 1 FROM password_check.bad_passwords bp WHERE ('md5' || md5(bp.plaintext || username)) = password ) INTO invalid; IF invalid THEN RAISE EXCEPTION 'Cannot use passwords from the common password dictionary'; END IF; ELSIF password_type = 'PASSWORD_TYPE_PLAINTEXT' THEN SELECT EXISTS( SELECT 1 FROM password_check.bad_passwords bp WHERE bp.plaintext = password ) INTO invalid; IF invalid THEN RAISE EXCEPTION 'Cannot use passwords from the common password dictionary'; END IF; END IF; -- Existing complexity check IF NOT (password ~ '[A-Z]' AND password ~ '[a-z]' AND password ~ '[0-9]' AND password ~ '[^a-zA-Z0-9]') THEN RAISE EXCEPTION 'Password must contain uppercase letters, lowercase letters, numbers, and special characters'; END IF; END $$ LANGUAGE plpgsql SECURITY DEFINER; GRANT EXECUTE ON FUNCTION password_check.passcheck_hook TO PUBLIC; SELECT pgtle.register_feature('password_check.passcheck_hook', 'passcheck'); $_pgtle_$ );
注: 要件に合わせてコードを変更してください。例えば、bad_passwords テーブルのパスワードを追加したり、パスワードの長さの要件を変更したり、パスワードの複雑さを確認したりできます。
パスワードが長さの要件を満たしているかどうかを確認するには、次のコマンドを実行します。
CREATE ROLE user1 PASSWORD '123456';
想定される出力:
ERROR: Password must be at least 8 characters long. CONTEXT: PL/pgSQL function password_check.passcheck_hook(text,text,pgtle.password_types,timestamptz,bool) SQL statement "SELECT password_check.passcheck_hook($1::pg_catalog.text, $2::pg_catalog.text, $3::pgtle.password_types, $4::pg_catalog.timestamptz, $5::pg_catalog.bool)"
注: 上記の例は、パスワードが 8 文字以上でなければならないため、エラーが発生したことを表しています。
パスワードが一般的すぎるかどうかを確認するには、次のコマンドを実行します。
CREATE ROLE user1 PASSWORD 'password';
想定される出力:
ERROR: Cannot use passwords from the common password dictionary CONTEXT: PL/pgSQL function password_check.passcheck_hook(text,text,pgtle.password_types,timestamptz,bool) SQL statement "SELECT password_check.passcheck_hook($1::pg_catalog.text, $2::pg_catalog.text, $3::pgtle.password_types, $4::pg_catalog.timestamptz, $5::pg_catalog.bool)"
注: 上記の例は、一般的なパスワード辞書のパスワードを使用できないため、エラーが発生したことを表しています。
パスワードの有効期限を確認するには、次の手順を実行します。
-
次のコマンドを実行して、ユーザーが最後にパスワードを変更した日時を確認します。
SELECT * FROM password_check.usertime WHERE user_name = 'user1';想定される出力:
user_name | lasttime ----------+---------------------------- user1 | 2025-10-01 18:48:07.319908 (1 row) -
次のコマンドを実行して、最終更新日を 91 日前に設定します。
UPDATE password_check.usertime SET lasttime = CURRENT_TIMESTAMP - INTERVAL '91 days' WHERE user_name = 'user1';想定される出力:
UPDATE 1 -
次のコマンドを実行して、最終更新日が 91 日前であることを確認します。
SELECT * FROM password_check.usertime WHERE user_name = 'user1';想定される出力:
user_name | lasttime ----------+---------------------------- user1 | 2025-07-02 18:55:36.248913 (1 row) -
次のコマンドを実行して、パスワードの有効期限機能をテストします。
ALTER USER user1 WITH PASSWORD 'NewTestPass786!';想定される出力:
NOTICE: Password has expired. It must be changed every 90 days. Last change was on 2025-07-02 18:55:36.248913 ALTER ROLE -
次のコマンドを実行して、ユーザーパスワードが変更され、最終更新日が更新されたことを確認します。
SELECT * FROM password_check.usertime WHERE user_name = 'user1';想定される出力:
user_name | lasttime ----------+---------------------------- user1 | 2025-10-01 19:18:42.028533 (1 row)
制限されたパスワード管理機能を有効にする
rds.restrict_password_commands パラメータを 1 に設定して、rds_password ロールを付与したデータベースユーザーのみがパスワードを管理できるようにします。
次の手順を実行します。
- DB クラスターパラメータグループを作成します。
- DB クラスターパラメータグループを DB クラスターに関連付けます。
- DB クラスターパラメータグループを変更して rds.restrict_password_commands を 1 に設定します。
注: 変更を適用するには、Aurora PostgreSQL 互換のプライマリ DB インスタンスを再起動する必要があります。
IAM データベース認証を使用する
IAM データベース認証では、パスワードではなく認証トークンを使用して DB クラスターに接続します。
IAM データベース認証を設定するには、次の手順を実行します。
- IAM データベース認証を有効にします。
- IAM データベースアクセス用の IAM ポリシーを作成します。
- プライマリユーザー、またはアクセス許可を作成および付与できるユーザーとして DB クラスターに接続します。
- ユーザーに rds_iam ロールを付与します。
- IAM 認証を使用して DB クラスターに接続します。
IAM ユーザー用のカスタムパスワードポリシーを作成する
詳細については、「IAM ユーザー用のアカウントパスワードポリシーを設定する」を参照してください。
AWS Secrets Manager を使用する
AWS Secrets Manager を使用してプライマリユーザーのパスワードを管理します。IAM 条件キーを使用して、Aurora によるプライマリユーザーのパスワードの管理を強制します。
詳細については、「Amazon Aurora および AWS Secrets Manager によるパスワード管理」を参照してください。
関連情報
New – Trusted Language Extensions for PostgreSQL on Amazon Aurora and Amazon RDS (新規 — Amazon Aurora と Amazon RDS 上の PostgreSQL 用の信頼できる Trusted Language Extensions)
