搭配您的延伸模組使用 PostgreSQL 掛鉤 - Amazon Aurora

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

搭配您的延伸模組使用 PostgreSQL 掛鉤

掛鉤是 PostgreSQL 中提供的回呼機制,允許開發人員在一般資料庫操作期間呼叫自訂函數或其他常式。TLE 開發套件支援 PostgreSQL 掛鉤,以便您可以在執行時整合自訂函數與 PostgreSQL 行為。例如,您可以使用掛鉤,將身分驗證程序與您自己的自訂程式碼建立關聯,或因應您的特定需求修改查詢規劃和執行程序。

您的 TLE 延伸模組可以使用掛鉤。如果掛鉤在範圍內是全域的,則其在所有資料庫之中都適用。因此,如果您的 TLE 延伸模組使用全域掛鉤,則您需要在使用者可以存取的所有資料庫中建立 TLE 延伸模組。

當使用 pg_tle 延伸模組來建置您自己的受信任語言延伸模組時,您可以使用 SQL API 中可用的掛鉤來建置延伸模組的函數。您應該使用 pg_tle 註冊任何掛鉤。對於某些掛鉤,您可能還需要設定各種組態參數。例如,passcode 檢查掛鉤可以設為開啟、關閉或需要。如需可用 pg_tle 掛鉤之特定需求的詳細資訊,請參閱 適用於 PostgreSQL 的受信任語言延伸模組的掛鉤參考

範例:建立使用 PostgreSQL 掛鉤的延伸模組

本節中討論的範例使用 PostgreSQL 掛鉤,來檢查在特定 SQL 操作期間提供的密碼,並防止資料庫使用者將其密碼設為 password_check.bad_passwords 資料表中包含的任何密碼。該資料表包含前十大最常用但容易破解的密碼選擇。

若要在您的 Aurora PostgreSQL 資料庫叢集 中設定此範例,您必須已安裝受信任語言延伸模組。如需詳細資訊,請參閱在您的 Aurora Postgre SQL 資料庫叢集中 Postgre 資料庫執行個體設定受信任語言擴充 SQL

設定密碼檢查掛鉤範例
  1. 使用 psql 連線到 Aurora PostgreSQL 資料庫叢集的寫入器執行個體。

    psql --host=db-instance-123456789012.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password --dbname=labdb
  2. 密碼檢查掛鉤程式碼清單 中複製程式碼,並將其貼入您的資料庫中。

    SELECT pgtle.install_extension ( 'my_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 password_check.bad_passwords (plaintext) AS VALUES ('123456'), ('password'), ('12345678'), ('qwerty'), ('123456789'), ('12345'), ('1234'), ('111111'), ('1234567'), ('dragon'); 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; BEGIN 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; 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_$ );

    將延伸模組載入資料庫後,您會看到如下輸出。

    install_extension ------------------- t (1 row)
  3. 在仍然連線到資料庫時,您現在可以建立延伸模組。

    CREATE EXTENSION my_password_check_rules;
  4. 您可以使用下列 psql 中繼命令,確認已在資料庫中建立延伸模組。

    \dx List of installed extensions Name | Version | Schema | Description -------------------------+---------+------------+------------------------------------------------------------- my_password_check_rules | 1.0 | public | Prevent use of any of the top-ten most common bad passwords pg_tle | 1.0.1 | pgtle | Trusted-Language Extensions for PostgreSQL plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language (3 rows)
  5. 開啟另一個終端機工作階段以使用 AWS CLI。您需要修改自訂資料庫參數群組,以開啟密碼檢查掛鉤。若要這麼做,請使用 modify-db-parameter-group 命令,如下列範例所示。

    aws rds modify-db-parameter-group \ --region aws-region \ --db-parameter-group-name your-custom-parameter-group \ --parameters "ParameterName=pgtle.enable_password_check,ParameterValue=on,ApplyMethod=immediate"

    可能需要幾分鐘,對參數群組設定所做的變更才會生效。不過,此參數是動態參數,因此您不需要重新啟動 Aurora PostgreSQL 資料庫叢集的寫入器執行個體,設定即可生效。

  6. 開啟 psql 工作階段並查詢資料庫,以驗證密碼檢查掛鉤是否已開啟。

    labdb=> SHOW pgtle.enable_password_check; pgtle.enable_password_check ----------------------------- on (1 row)

密碼檢查掛鉤現在處於作用中狀態。您可以建立新角色並使用其中一個錯誤密碼來對它進行測試,如下列範例所示。

CREATE ROLE test_role PASSWORD 'password'; ERROR: Cannot use passwords from the common password dictionary CONTEXT: PL/pgSQL function password_check.passcheck_hook(text,text,pgtle.password_types,timestamp with time zone,boolean) line 21 at RAISE 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)"

為了方便閱讀,輸出已經過格式化處理。

下列範例顯示 pgsql 互動式中繼命令 \password 行為也受密碼檢查掛鉤的影響。

postgres=> SET password_encryption TO 'md5'; SET postgres=> \password Enter new password for user "postgres":***** Enter it again:***** ERROR: Cannot use passwords from the common password dictionary CONTEXT: PL/pgSQL function password_check.passcheck_hook(text,text,pgtle.password_types,timestamp with time zone,boolean) line 12 at RAISE 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)"

如果需要,您可以捨棄此 TLE 延伸模組並解除安裝其來源檔案。如需詳細資訊,請參閱從數據庫中刪除TLE擴展

密碼檢查掛鉤程式碼清單

此處顯示的範例程式碼定義了 my_password_check_rules TLE 延伸模組的規格。當您複製此程式碼並將其貼入資料庫中時,my_password_check_rules 延伸模組的程式碼會載入至資料庫,而且 password_check 掛鉤會進行註冊以供該延伸模組使用。

SELECT pgtle.install_extension ( 'my_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 password_check.bad_passwords (plaintext) AS VALUES ('123456'), ('password'), ('12345678'), ('qwerty'), ('123456789'), ('12345'), ('1234'), ('111111'), ('1234567'), ('dragon'); 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; BEGIN 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; 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_$ );