Skip to content

Commit b07f54f

Browse files
Introduce a read-only user for data-replication
- User must be created within aws account due to database living in private subnet - For simplicity just create user on startup of application if does not already exist - Password is managed via terraform and injected into container
1 parent 3425508 commit b07f54f

4 files changed

Lines changed: 76 additions & 1 deletion

File tree

bin/data-replication

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#!/usr/bin/env bash
2+
3+
# Data replication script - creates read-only database role and keeps container running
4+
5+
set -e
6+
7+
echo "Starting data replication setup..."
8+
9+
if [ -z "$RO_DB_PASSWORD" ]; then
10+
echo "Error: RO_DB_PASSWORD environment variable is not set"
11+
exit 1
12+
fi
13+
14+
echo "Creating read-only database role..."
15+
16+
bundle exec rails runner "
17+
begin
18+
ActiveRecord::Base.connection.execute(\"
19+
DO \$\$
20+
BEGIN
21+
IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = 'readonly_user') THEN
22+
CREATE ROLE readonly_user WITH LOGIN PASSWORD '#{ENV['RO_DB_PASSWORD']}';
23+
ELSE
24+
ALTER ROLE readonly_user WITH PASSWORD '#{ENV['RO_DB_PASSWORD']}';
25+
END IF;
26+
END
27+
\$\$;
28+
\")
29+
30+
ActiveRecord::Base.connection.execute(\"
31+
GRANT CONNECT ON DATABASE #{ActiveRecord::Base.connection.current_database} TO readonly_user;
32+
GRANT USAGE ON SCHEMA public TO readonly_user;
33+
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly_user;
34+
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO readonly_user;
35+
\")
36+
37+
puts 'Read-only role created/updated successfully'
38+
rescue => e
39+
puts \"Error creating read-only role: \#{e.message}\"
40+
exit 1
41+
end
42+
"
43+
44+
echo "Data replication setup completed. Keeping container running..."
45+
46+
exec tail -f /dev/null

bin/docker-start

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,13 @@ elif [ "$SERVER_TYPE" == "good-job" ]; then
1111
elif [ "$SERVER_TYPE" == "sidekiq" ]; then
1212
echo "Starting sidekiq server..."
1313
exec "$BIN_DIR"/sidekiq
14+
elif [ "$SERVER_TYPE" == "data-replication" ]; then
15+
echo "Starting data replication server..."
16+
exec "$BIN_DIR"/data-replication
1417
elif [ "$SERVER_TYPE" == "none" ]; then
1518
echo "No server started"
1619
exec tail -f /dev/null # Keep container running
1720
else
18-
echo "SERVER_TYPE variable: '$SERVER_TYPE' unknown. Allowed values ['web','good-job', 'none']"
21+
echo "SERVER_TYPE variable: '$SERVER_TYPE' unknown. Allowed values ['web','good-job', 'sidekiq', 'data-replication', 'none']"
1922
exit 1
2023
fi
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Create a password that is automatically populated in secrets manager using the random password generator for aws
2+
3+
# Generate a random password for the read-only database user
4+
ephemeral "aws_secretsmanager_random_password" "ro_db_password" {
5+
}
6+
7+
# Store the generated password in AWS Secrets Manager
8+
resource "aws_secretsmanager_secret" "ro_db_password" {
9+
name = "${local.name_prefix}-ro-db-password-${substr(uuid(), 0, 4)}"
10+
description = "Read-only database user password for data replication"
11+
recovery_window_in_days = 7
12+
13+
tags = {
14+
Name = "${local.name_prefix}-ro-db-password"
15+
}
16+
}
17+
18+
resource "aws_secretsmanager_secret_version" "ro_db_password" {
19+
secret_id = aws_secretsmanager_secret.ro_db_password.id
20+
secret_string_wo = ephemeral.aws_secretsmanager_random_password.ro_db_password.random_password
21+
secret_string_wo_version = 1
22+
}

terraform/data_replication/variables.tf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,10 @@ locals {
124124
{
125125
name = "RAILS_MASTER_KEY"
126126
valueFrom = var.rails_master_key_path
127+
},
128+
{
129+
name = "RO_DB_PASSWORD"
130+
valueFrom = aws_secretsmanager_secret.ro_db_password.arn
127131
}
128132
]
129133
}

0 commit comments

Comments
 (0)