Skip to content

Commit

Permalink
Merge pull request #3 from railwayapp-templates/x509v3-certs
Browse files Browse the repository at this point in the history
generate x509v3 certs
  • Loading branch information
brody192 authored Aug 12, 2024
2 parents f64411f + bd4ab06 commit 02f73c8
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 58 deletions.
14 changes: 4 additions & 10 deletions Dockerfile.pg13-ts2.12
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,11 @@ USER root
RUN apt-get update && apt-get install -y openssl sudo

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

# Add entrypoint wrapper
COPY wrapper.sh /usr/local/bin/wrapper.sh

# Add init script
COPY init-ssl.sh /docker-entrypoint-initdb.d/

# Set permissions
RUN chmod +x /usr/local/bin/wrapper.sh
RUN chmod +x /docker-entrypoint-initdb.d/init-ssl.sh
# Add init scripts while setting permissions
COPY --chmod=755 init-ssl.sh /docker-entrypoint-initdb.d/init-ssl.sh
COPY --chmod=755 wrapper.sh /usr/local/bin/wrapper.sh

# Switch back to the postgres
USER postgres
Expand Down
14 changes: 4 additions & 10 deletions Dockerfile.pg14-ts2.12
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,11 @@ USER root
RUN apt-get update && apt-get install -y openssl sudo

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

# Add entrypoint wrapper
COPY wrapper.sh /usr/local/bin/wrapper.sh

# Add init script
COPY init-ssl.sh /docker-entrypoint-initdb.d/

# Set permissions
RUN chmod +x /usr/local/bin/wrapper.sh
RUN chmod +x /docker-entrypoint-initdb.d/init-ssl.sh
# Add init scripts while setting permissions
COPY --chmod=755 init-ssl.sh /docker-entrypoint-initdb.d/init-ssl.sh
COPY --chmod=755 wrapper.sh /usr/local/bin/wrapper.sh

# Switch back to the postgres
USER postgres
Expand Down
14 changes: 4 additions & 10 deletions Dockerfile.pg15-ts2.12
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,11 @@ USER root
RUN apt-get update && apt-get install -y openssl sudo

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

# Add entrypoint wrapper
COPY wrapper.sh /usr/local/bin/wrapper.sh

# Add init script
COPY init-ssl.sh /docker-entrypoint-initdb.d/

# Set permissions
RUN chmod +x /usr/local/bin/wrapper.sh
RUN chmod +x /docker-entrypoint-initdb.d/init-ssl.sh
# Add init scripts while setting permissions
COPY --chmod=755 init-ssl.sh /docker-entrypoint-initdb.d/init-ssl.sh
COPY --chmod=755 wrapper.sh /usr/local/bin/wrapper.sh

# Switch back to the postgres
USER postgres
Expand Down
14 changes: 4 additions & 10 deletions Dockerfile.pg16-ts2.13
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,11 @@ USER root
RUN apt-get update && apt-get install -y openssl sudo

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

# Add entrypoint wrapper
COPY wrapper.sh /usr/local/bin/wrapper.sh

# Add init script
COPY init-ssl.sh /docker-entrypoint-initdb.d/

# Set permissions
RUN chmod +x /usr/local/bin/wrapper.sh
RUN chmod +x /docker-entrypoint-initdb.d/init-ssl.sh
# Add init scripts while setting permissions
COPY --chmod=755 init-ssl.sh /docker-entrypoint-initdb.d/init-ssl.sh
COPY --chmod=755 wrapper.sh /usr/local/bin/wrapper.sh

# Switch back to the postgres
USER postgres
Expand Down
60 changes: 44 additions & 16 deletions init-ssl.sh
Original file line number Diff line number Diff line change
@@ -1,29 +1,57 @@
#!/bin/bash

# exit as soon as any of these commands fail, this prevents starting a database without certificates
set -e

# Set up needed variables
SSL_DIR="/var/lib/postgresql/data/certs"

SSL_SERVER_CRT="$SSL_DIR/server.crt"
SSL_SERVER_KEY="$SSL_DIR/server.key"
SSL_SERVER_CSR="$SSL_DIR/server.csr"

SSL_ROOT_KEY="$SSL_DIR/root.key"
SSL_ROOT_CRT="$SSL_DIR/root.crt"

SSL_V3_EXT="$SSL_DIR/v3.ext"

POSTGRES_CONF_FILE="$PGDATA/postgresql.conf"

# Use sudo to create the directory as root
sudo mkdir -p "$SSL_DIR"

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

# Check if certificates already exist
if [ ! -f "$SSL_DIR/server.key" ] || [ ! -f "$SSL_DIR/server.crt" ] || [ ! -f "$SSL_DIR/root.crt" ]; then
# Generate Root CA
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"
# Generate self-signed 509v3 certificates
# ref: https://www.postgresql.org/docs/16/ssl-tcp.html#SSL-CERTIFICATE-CREATION

# Generate Server Certificates
openssl req -new -nodes -text -out "$SSL_DIR/server.csr" -keyout "$SSL_DIR/server.key" -subj "/CN=localhost"
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
openssl req -new -x509 -days "${SSL_CERT_DAYS:-820}" -nodes -text -out "$SSL_ROOT_CRT" -keyout "$SSL_ROOT_KEY" -subj "/CN=root-ca"

chown postgres:postgres "$SSL_DIR/server.key"
chmod 600 "$SSL_DIR/server.key"
fi
chmod og-rwx "$SSL_ROOT_KEY"

# PostgreSQL configuration
cat >> "$PGDATA/postgresql.conf" <<EOF
ssl = on
ssl_cert_file = '$SSL_DIR/server.crt'
ssl_key_file = '$SSL_DIR/server.key'
ssl_ca_file = '$SSL_DIR/root.crt'
openssl req -new -nodes -text -out "$SSL_SERVER_CSR" -keyout "$SSL_SERVER_KEY" -subj "/CN=localhost"

chown postgres:postgres "$SSL_SERVER_KEY"

chmod og-rwx "$SSL_SERVER_KEY"

cat >| "$SSL_V3_EXT" <<EOF
[v3_req]
authorityKeyIdentifier = keyid, issuer
basicConstraints = critical, CA:TRUE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = DNS:localhost
EOF

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"

chown postgres:postgres "$SSL_SERVER_CRT"

# PostgreSQL configuration, enable ssl and set paths to certificate files
cat >> "$POSTGRES_CONF_FILE" <<EOF
ssl = on
ssl_cert_file = '$SSL_SERVER_CRT'
ssl_key_file = '$SSL_SERVER_KEY'
ssl_ca_file = '$SSL_ROOT_CRT'
EOF
43 changes: 41 additions & 2 deletions wrapper.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,39 @@
#!/bin/bash

# exit as soon as any of these commands fail, this prevents starting a database without certificates
set -e

# Make sure there is a PGDATA variable available
if [ -z "$PGDATA" ]; then
echo "Missing PGDATA variable"
exit 1
fi

# Set up needed variables
SSL_DIR="/var/lib/postgresql/data/certs"
INIT_SSL_SCRIPT="/docker-entrypoint-initdb.d/init-ssl.sh"
POSTGRES_CONF_FILE="$PGDATA/postgresql.conf"

# Regenerate if the certificate is not a x509v3 certificate
if [ -f "$SSL_DIR/server.crt" ] && ! openssl x509 -noout -text -in "$SSL_DIR/server.crt" | grep -q "DNS:localhost"; then
echo "Did not find a x509v3 certificate, regenerating certificates..."
bash "$INIT_SSL_SCRIPT"
fi

# Regenerate if the certificate has expired or will expire
# 2592000 seconds = 30 days
if [ -f "$SSL_DIR/server.crt" ] && ! openssl x509 -checkend 2592000 -noout -in "$SSL_DIR/server.crt"; then
echo "Certificate has or will expire soon, regenerating certificates..."
bash "$INIT_SSL_SCRIPT"
fi

# Generate a certificate if the database was initialized but is missing a certificate
# Useful when going from the base postgres image to this ssl image
if [ -f "$POSTGRES_CONF_FILE" ] && [ ! -f "$SSL_DIR/server.crt" ]; then
echo "Database initialized without certificate, generating certificates..."
bash "$INIT_SSL_SCRIPT"
fi

# unset PGHOST to force psql to use Unix socket path
# this is specific to Railway and allows
# us to use PGHOST after the init
Expand All @@ -12,5 +46,10 @@ unset PGHOST
unset PGPORT

# Call the entrypoint script with the
# approriate PGHOST
/docker-entrypoint.sh "$@"
# appropriate PGHOST & PGPORT and redirect
# the output to stdout if LOG_TO_STDOUT is true
if [[ "$LOG_TO_STDOUT" == "true" ]]; then
/usr/local/bin/docker-entrypoint.sh "$@" 2>&1
else
/usr/local/bin/docker-entrypoint.sh "$@"
fi

0 comments on commit 02f73c8

Please sign in to comment.