diff --git a/misc/generate_password.sql b/misc/generate_password.sql index 53b435e..5bc47a8 100644 --- a/misc/generate_password.sql +++ b/misc/generate_password.sql @@ -1,6 +1,5 @@ --- WARNING: random() that is used here is not cryptographically strong – --- if an attacker knows one value, it's easy to guess the "next" value --- TODO: rework to use pgcrypto instead +-- This script uses pgcrypto extension to generate cryptographically secure random passwords +-- You need to enable the pgcrypto extension first with: CREATE EXTENSION IF NOT EXISTS pgcrypto; with init(len, arr) as ( -- edit password length and possible characters here @@ -9,7 +8,8 @@ with init(len, arr) as ( select count(*) from (select unnest(arr) from init) _ ), indexes(i) as ( - select 1 + int4(random() * (l - 1)) + -- Using gen_random_bytes from pgcrypto for cryptographically secure randomness + select 1 + (get_byte(gen_random_bytes(1), 0)::int % (l - 1)) from arrlen, (select generate_series(1, len) from init) _ ), res as ( select array_to_string(array_agg(arr[i]), '') as password diff --git a/roles/alter_user_with_random_password.psql b/roles/alter_user_with_random_password.psql index f951c87..1d25db6 100644 --- a/roles/alter_user_with_random_password.psql +++ b/roles/alter_user_with_random_password.psql @@ -4,9 +4,11 @@ -- This interactive script solves this problem. -- Usage (run in psql): --- 1) Set messages level to DEBUG (and keep logging level higher, to avoid having password in logs): +-- 1) Make sure the pgcrypto extension is installed: +-- CREATE EXTENSION IF NOT EXISTS pgcrypto; +-- 2) Set messages level to DEBUG (and keep logging level higher, to avoid having password in logs): -- set client_min_messages to DEBUG; --- 2) Run interactive script in psql: +-- 3) Run interactive script in psql: -- \i /path/to/PostgresDBA/roles/alter_user_with_random_password.psql \prompt "Username?" postgres_dba_username @@ -40,7 +42,8 @@ begin allowed_len := length(allowed); pwd := ''; while length(pwd) < 16 loop - j := int4(random() * allowed_len); + -- Using gen_random_bytes from pgcrypto for cryptographically secure randomness + j := get_byte(gen_random_bytes(1), 0) % allowed_len; pwd := pwd || substr(allowed, j+1, 1); end loop; sql := 'alter role ' || current_setting('postgres_dba.username')::text || ' password ''' || pwd || ''';'; diff --git a/roles/create_user_with_random_password.psql b/roles/create_user_with_random_password.psql index a5257a3..dcd7551 100644 --- a/roles/create_user_with_random_password.psql +++ b/roles/create_user_with_random_password.psql @@ -4,9 +4,11 @@ -- This interactive script solves this problem. -- Usage (run in psql): --- 1) Set messages level to DEBUG (and keep logging level higher, to avoid having password in logs): +-- 1) Make sure the pgcrypto extension is installed: +-- CREATE EXTENSION IF NOT EXISTS pgcrypto; +-- 2) Set messages level to DEBUG (and keep logging level higher, to avoid having password in logs): -- set client_min_messages to DEBUG; --- 2) Run interactive script in psql: +-- 3) Run interactive script in psql: -- \i /path/to/PostgresDBA/roles/create_user_with_random_password.psql \prompt "Username?" postgres_dba_username @@ -40,7 +42,8 @@ begin allowed_len := length(allowed); pwd := ''; while length(pwd) < 16 loop - j := int4(random() * allowed_len); + -- Using gen_random_bytes from pgcrypto for cryptographically secure randomness + j := get_byte(gen_random_bytes(1), 0) % allowed_len; pwd := pwd || substr(allowed, j+1, 1); end loop; sql := 'create role ' || current_setting('postgres_dba.username')::text