Skip to content

Commit 02f73c8

Browse files
authored
Merge pull request #3 from railwayapp-templates/x509v3-certs
generate x509v3 certs
2 parents f64411f + bd4ab06 commit 02f73c8

6 files changed

+101
-58
lines changed

Dockerfile.pg13-ts2.12

+4-10
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,11 @@ USER root
77
RUN apt-get update && apt-get install -y openssl sudo
88

99
# Allow the postgres user to execute certain commands as root without a password
10-
RUN echo "postgres ALL=(root) NOPASSWD: /usr/bin/mkdir, /bin/chown" > /etc/sudoers.d/postgres
10+
RUN echo "postgres ALL=(root) NOPASSWD: /usr/bin/mkdir, /bin/chown, /usr/bin/openssl" > /etc/sudoers.d/postgres
1111

12-
# Add entrypoint wrapper
13-
COPY wrapper.sh /usr/local/bin/wrapper.sh
14-
15-
# Add init script
16-
COPY init-ssl.sh /docker-entrypoint-initdb.d/
17-
18-
# Set permissions
19-
RUN chmod +x /usr/local/bin/wrapper.sh
20-
RUN chmod +x /docker-entrypoint-initdb.d/init-ssl.sh
12+
# Add init scripts while setting permissions
13+
COPY --chmod=755 init-ssl.sh /docker-entrypoint-initdb.d/init-ssl.sh
14+
COPY --chmod=755 wrapper.sh /usr/local/bin/wrapper.sh
2115

2216
# Switch back to the postgres
2317
USER postgres

Dockerfile.pg14-ts2.12

+4-10
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,11 @@ USER root
77
RUN apt-get update && apt-get install -y openssl sudo
88

99
# Allow the postgres user to execute certain commands as root without a password
10-
RUN echo "postgres ALL=(root) NOPASSWD: /usr/bin/mkdir, /bin/chown" > /etc/sudoers.d/postgres
10+
RUN echo "postgres ALL=(root) NOPASSWD: /usr/bin/mkdir, /bin/chown, /usr/bin/openssl" > /etc/sudoers.d/postgres
1111

12-
# Add entrypoint wrapper
13-
COPY wrapper.sh /usr/local/bin/wrapper.sh
14-
15-
# Add init script
16-
COPY init-ssl.sh /docker-entrypoint-initdb.d/
17-
18-
# Set permissions
19-
RUN chmod +x /usr/local/bin/wrapper.sh
20-
RUN chmod +x /docker-entrypoint-initdb.d/init-ssl.sh
12+
# Add init scripts while setting permissions
13+
COPY --chmod=755 init-ssl.sh /docker-entrypoint-initdb.d/init-ssl.sh
14+
COPY --chmod=755 wrapper.sh /usr/local/bin/wrapper.sh
2115

2216
# Switch back to the postgres
2317
USER postgres

Dockerfile.pg15-ts2.12

+4-10
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,11 @@ USER root
77
RUN apt-get update && apt-get install -y openssl sudo
88

99
# Allow the postgres user to execute certain commands as root without a password
10-
RUN echo "postgres ALL=(root) NOPASSWD: /usr/bin/mkdir, /bin/chown" > /etc/sudoers.d/postgres
10+
RUN echo "postgres ALL=(root) NOPASSWD: /usr/bin/mkdir, /bin/chown, /usr/bin/openssl" > /etc/sudoers.d/postgres
1111

12-
# Add entrypoint wrapper
13-
COPY wrapper.sh /usr/local/bin/wrapper.sh
14-
15-
# Add init script
16-
COPY init-ssl.sh /docker-entrypoint-initdb.d/
17-
18-
# Set permissions
19-
RUN chmod +x /usr/local/bin/wrapper.sh
20-
RUN chmod +x /docker-entrypoint-initdb.d/init-ssl.sh
12+
# Add init scripts while setting permissions
13+
COPY --chmod=755 init-ssl.sh /docker-entrypoint-initdb.d/init-ssl.sh
14+
COPY --chmod=755 wrapper.sh /usr/local/bin/wrapper.sh
2115

2216
# Switch back to the postgres
2317
USER postgres

Dockerfile.pg16-ts2.13

+4-10
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,11 @@ USER root
77
RUN apt-get update && apt-get install -y openssl sudo
88

99
# Allow the postgres user to execute certain commands as root without a password
10-
RUN echo "postgres ALL=(root) NOPASSWD: /usr/bin/mkdir, /bin/chown" > /etc/sudoers.d/postgres
10+
RUN echo "postgres ALL=(root) NOPASSWD: /usr/bin/mkdir, /bin/chown, /usr/bin/openssl" > /etc/sudoers.d/postgres
1111

12-
# Add entrypoint wrapper
13-
COPY wrapper.sh /usr/local/bin/wrapper.sh
14-
15-
# Add init script
16-
COPY init-ssl.sh /docker-entrypoint-initdb.d/
17-
18-
# Set permissions
19-
RUN chmod +x /usr/local/bin/wrapper.sh
20-
RUN chmod +x /docker-entrypoint-initdb.d/init-ssl.sh
12+
# Add init scripts while setting permissions
13+
COPY --chmod=755 init-ssl.sh /docker-entrypoint-initdb.d/init-ssl.sh
14+
COPY --chmod=755 wrapper.sh /usr/local/bin/wrapper.sh
2115

2216
# Switch back to the postgres
2317
USER postgres

init-ssl.sh

+44-16
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,57 @@
11
#!/bin/bash
2+
3+
# exit as soon as any of these commands fail, this prevents starting a database without certificates
4+
set -e
5+
6+
# Set up needed variables
27
SSL_DIR="/var/lib/postgresql/data/certs"
38

9+
SSL_SERVER_CRT="$SSL_DIR/server.crt"
10+
SSL_SERVER_KEY="$SSL_DIR/server.key"
11+
SSL_SERVER_CSR="$SSL_DIR/server.csr"
12+
13+
SSL_ROOT_KEY="$SSL_DIR/root.key"
14+
SSL_ROOT_CRT="$SSL_DIR/root.crt"
15+
16+
SSL_V3_EXT="$SSL_DIR/v3.ext"
17+
18+
POSTGRES_CONF_FILE="$PGDATA/postgresql.conf"
19+
420
# Use sudo to create the directory as root
521
sudo mkdir -p "$SSL_DIR"
622

723
# Use sudo to change ownership as root
824
sudo chown postgres:postgres "$SSL_DIR"
925

10-
# Check if certificates already exist
11-
if [ ! -f "$SSL_DIR/server.key" ] || [ ! -f "$SSL_DIR/server.crt" ] || [ ! -f "$SSL_DIR/root.crt" ]; then
12-
# Generate Root CA
13-
openssl req -new -x509 -days "${SSL_CERT_DAYS:-820}" -nodes -text -out "$SSL_DIR/root.crt" -keyout "$SSL_DIR/root.key" -subj "/CN=root-ca"
26+
# Generate self-signed 509v3 certificates
27+
# ref: https://www.postgresql.org/docs/16/ssl-tcp.html#SSL-CERTIFICATE-CREATION
1428

15-
# Generate Server Certificates
16-
openssl req -new -nodes -text -out "$SSL_DIR/server.csr" -keyout "$SSL_DIR/server.key" -subj "/CN=localhost"
17-
openssl x509 -req -in "$SSL_DIR/server.csr" -text -out "$SSL_DIR/server.crt" -CA "$SSL_DIR/root.crt" -CAkey "$SSL_DIR/root.key" -CAcreateserial
29+
openssl req -new -x509 -days "${SSL_CERT_DAYS:-820}" -nodes -text -out "$SSL_ROOT_CRT" -keyout "$SSL_ROOT_KEY" -subj "/CN=root-ca"
1830

19-
chown postgres:postgres "$SSL_DIR/server.key"
20-
chmod 600 "$SSL_DIR/server.key"
21-
fi
31+
chmod og-rwx "$SSL_ROOT_KEY"
2232

23-
# PostgreSQL configuration
24-
cat >> "$PGDATA/postgresql.conf" <<EOF
25-
ssl = on
26-
ssl_cert_file = '$SSL_DIR/server.crt'
27-
ssl_key_file = '$SSL_DIR/server.key'
28-
ssl_ca_file = '$SSL_DIR/root.crt'
33+
openssl req -new -nodes -text -out "$SSL_SERVER_CSR" -keyout "$SSL_SERVER_KEY" -subj "/CN=localhost"
34+
35+
chown postgres:postgres "$SSL_SERVER_KEY"
36+
37+
chmod og-rwx "$SSL_SERVER_KEY"
38+
39+
cat >| "$SSL_V3_EXT" <<EOF
40+
[v3_req]
41+
authorityKeyIdentifier = keyid, issuer
42+
basicConstraints = critical, CA:TRUE
43+
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
44+
subjectAltName = DNS:localhost
2945
EOF
46+
47+
openssl x509 -req -in "$SSL_SERVER_CSR" -extfile "$SSL_V3_EXT" -extensions v3_req -text -days "${SSL_CERT_DAYS:-820}" -CA "$SSL_ROOT_CRT" -CAkey "$SSL_ROOT_KEY" -CAcreateserial -out "$SSL_SERVER_CRT"
48+
49+
chown postgres:postgres "$SSL_SERVER_CRT"
50+
51+
# PostgreSQL configuration, enable ssl and set paths to certificate files
52+
cat >> "$POSTGRES_CONF_FILE" <<EOF
53+
ssl = on
54+
ssl_cert_file = '$SSL_SERVER_CRT'
55+
ssl_key_file = '$SSL_SERVER_KEY'
56+
ssl_ca_file = '$SSL_ROOT_CRT'
57+
EOF

wrapper.sh

+41-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,39 @@
11
#!/bin/bash
22

3+
# exit as soon as any of these commands fail, this prevents starting a database without certificates
4+
set -e
5+
6+
# Make sure there is a PGDATA variable available
7+
if [ -z "$PGDATA" ]; then
8+
echo "Missing PGDATA variable"
9+
exit 1
10+
fi
11+
12+
# Set up needed variables
13+
SSL_DIR="/var/lib/postgresql/data/certs"
14+
INIT_SSL_SCRIPT="/docker-entrypoint-initdb.d/init-ssl.sh"
15+
POSTGRES_CONF_FILE="$PGDATA/postgresql.conf"
16+
17+
# Regenerate if the certificate is not a x509v3 certificate
18+
if [ -f "$SSL_DIR/server.crt" ] && ! openssl x509 -noout -text -in "$SSL_DIR/server.crt" | grep -q "DNS:localhost"; then
19+
echo "Did not find a x509v3 certificate, regenerating certificates..."
20+
bash "$INIT_SSL_SCRIPT"
21+
fi
22+
23+
# Regenerate if the certificate has expired or will expire
24+
# 2592000 seconds = 30 days
25+
if [ -f "$SSL_DIR/server.crt" ] && ! openssl x509 -checkend 2592000 -noout -in "$SSL_DIR/server.crt"; then
26+
echo "Certificate has or will expire soon, regenerating certificates..."
27+
bash "$INIT_SSL_SCRIPT"
28+
fi
29+
30+
# Generate a certificate if the database was initialized but is missing a certificate
31+
# Useful when going from the base postgres image to this ssl image
32+
if [ -f "$POSTGRES_CONF_FILE" ] && [ ! -f "$SSL_DIR/server.crt" ]; then
33+
echo "Database initialized without certificate, generating certificates..."
34+
bash "$INIT_SSL_SCRIPT"
35+
fi
36+
337
# unset PGHOST to force psql to use Unix socket path
438
# this is specific to Railway and allows
539
# us to use PGHOST after the init
@@ -12,5 +46,10 @@ unset PGHOST
1246
unset PGPORT
1347

1448
# Call the entrypoint script with the
15-
# approriate PGHOST
16-
/docker-entrypoint.sh "$@"
49+
# appropriate PGHOST & PGPORT and redirect
50+
# the output to stdout if LOG_TO_STDOUT is true
51+
if [[ "$LOG_TO_STDOUT" == "true" ]]; then
52+
/usr/local/bin/docker-entrypoint.sh "$@" 2>&1
53+
else
54+
/usr/local/bin/docker-entrypoint.sh "$@"
55+
fi

0 commit comments

Comments
 (0)