Commit d2022282 authored by Adam Lewenberg's avatar Adam Lewenberg
Browse files

more work on lets-encrypt

parent 54a331cf
Loading
Loading
Loading
Loading
+77 −0
Original line number Diff line number Diff line
#!/bin/bash

# Link a key-pair in /etc/ssl/certs and /etc/ssl/private to the
# corresponding Let's Encrypt key-pair. If the Let's Encrypt key-pair
# does not exist link to snake-oil.


# Use:     link-le-cert.sh <fqdn>
# Example: link-le-cert.sh debian-repo-dev.stanford.edu

# Returns 0 if the linking was necessary, 1 if no linking needed.

PATH=/usr/bin:/usr/sbin

CERTNAME=$1

if [[ -z "$CERTNAME" ]]; then
    echo "error: missing required argument"
    exit 1
fi

###################################################################################
md5calc () {
    local path="$1"

    if [[ -f "$path" ]]; then
        md5sum "$path" | cut -f1 -d' '
    else
        echo '00000000000000000000000000000000'
    fi
}

###################################################################################

MAIN_KEY="/etc/ssl/private/${CERTNAME}.key"
MAIN_CERT="/etc/ssl/certs/${CERTNAME}.pem"

LETS_ENCRYPT_KEY="/etc/letsencrypt/live/${CERTNAME}/privkey.pem"
LETS_ENCRYPT_CERT="/etc/letsencrypt/live/${CERTNAME}/fullchain.pem"

SNAKEOIL_KEY="/etc/ssl/private/ssl-cert-snakeoil.key"
SNAKEOIL_CERT="/etc/ssl/certs/ssl-cert-snakeoil.pem"
SNAKEOIL_SUBJECT="/C=US/ST=California/L=Stanford/O=Stanford University/OU=IEDO/CN=$CERTNAME"

# Step 1: make sure the snake-oil key-pair exists. If not, create it.
if [[ ! -f "$SNAKEOIL_KEY" ]] || [[ ! -f "$SNAKEOIL_CERT" ]]; then
    openssl req -x509 -nodes -newkey rsa:2048 \
            -keyout "$SNAKEOIL_KEY" -out "$SNAKEOIL_CERT" \
            -days 3650 -subj "$SNAKEOIL_SUBJECT" > /dev/null
fi

# Step 2: check hashes to determine if we need to link.
if [[ -f "$LETS_ENCRYPT_KEY" ]] && [[ -f "$LETS_ENCRYPT_CERT" ]]; then
    SRC_KEY="$LETS_ENCRYPT_KEY"
    SRC_CERT="$LETS_ENCRYPT_CERT"
else
    SRC_KEY="$SNAKEOIL_KEY"
    SRC_CERT="$SNAKEOIL_CERT"
fi

MD5SUM_SRC_KEY=$(md5calc "$SRC_KEY")
MD5SUM_SRC_CERT=$(md5calc "$SRC_CERT")

MD5SUM_MAIN_KEY=$(md5calc "$MAIN_KEY")
MD5SUM_MAIN_CERT=$(md5calc "$MAIN_CERT")

if [[ "$MD5SUM_SRC_KEY" == "$MD5SUM_MAIN_KEY" ]] && [[ "$MD5SUM_SRC_CERT" == "$MD5SUM_MAIN_CERT" ]]; then
    # The hashes match, so nothing to do except set the return code to 1.
    RC=1
else
    # The hashes do NOT match, so we need to link.
    ln -s --force "$SRC_KEY"  "$MAIN_KEY"
    ln -s --force "$SRC_CERT" "$MAIN_CERT"
    RC=0
fi

exit "$RC"
+11 −75
Original line number Diff line number Diff line
@@ -14,85 +14,21 @@
# cert-name of the Let's Encrypt certificate, i.e., must match
# the directory /etc/letsencrypt/live/<FQDN>.

define su_apache::cert::lets_encrypt (
  String $lets_encrypt_basedir = '/etc/letsencrypt',
) {
define su_apache::cert::lets_encrypt {

  # $main_key/$main_cert will be linked to either the snake-oil key-pair
  # or the Let's Encrypt key-pair.
  $main_key  = "/etc/ssl/private/${name}.key"
  $main_cert = "/etc/ssl/certs/${name}.pem"

  $le_key  = "${lets_encrypt_basedir}/live/${name}/privkey.pem"
  $le_cert = "${lets_encrypt_basedir}/live/${name}/fullchain.pem"

  $so_key  = '/etc/ssl/private/ssl-cert-snakeoil.key'
  $so_cert = '/etc/ssl/certs/ssl-cert-snakeoil.pem'

  ## STAGE 1.
  # Make sure the snake-oil key-pair always exists. This is useful
  # in case the Let's Encrypt certificate does not (yet) exists.
  # Only run if it does not already exists.
  $subject = "/C=US/ST=California/L=Stanford/O=Stanford University/OU=IEDO/CN=${name}"
  exec { 'create-snake-oil':
    path    => '/usr/bin:/usr/sbin',
    command => [
            'openssl',
            'req',
            '-x509',
            '-nodes',
            '-newkey', 'rsa:2048',
            '-keyout', $so_key,
            '-out',    $so_cert,
            '-days',   '3650',
            '-subj',   $subject,
    ],
    creates => $so_key,
  file { '/usr/sbin/link-lets-encrypt-certs':
    ensure => present,
    source => 'puppet:///modules/su_apache/usr/sbin/link-lets-encrypt-certs',
    mode   => '0755',
  }


  # In the following, because of the onlyif's exactly one of 2A and 2B
  # will execute.

  ## STAGE 2A.
  # Link the main key-pair to the snake-old key-pair, but only if the
  # Let's Encrypt key-pair does NOT exist.

  # This command returns 0 if either Let's Encrypt file does NOT exist.
  $onlyif_cmd_so = "sh -c \"test ! -f ${le_cert} || test ! -f ${le_key}\""

  # This is the command that does the linking.
  # We pass ln the --force option to overwrite any file that
  # may already be there.
  $cmd1_so     = "ln -s --force ${so_key} ${main_key}"
  $cmd2_so     = "ln -s --force ${so_cert} ${main_cert}"
  $link_cmd_so = "${cmd1_so} && ${cmd2_so}"

  exec { "link-${name}-to-so":
    path    => '/usr/bin:/usr/sbin',
    command => $link_cmd_so,
    onlyif  => $onlyif_cmd_so,
  }

  ## STAGE 2B.
  # Link the main key-pair to the Let's Encrypt key-pair, but only if
  # the Let's Encrypt key-pair exists.

  # This is the command that returns 0 if both Let's Encrypt files
  # exist. We only link to them if they are in place.
  $onlyif_cmd_le = "sh -c \"test -f ${le_cert} && test -f ${le_key}\""

  # This is the command that does the linking.
  # We pass ln the --force option to overwrite any file that
  # may already be there.
  $cmd1_le     = "ln -s --force ${le_key} ${main_key}"
  $cmd2_le     = "ln -s --force ${le_cert} ${main_cert}"
  $link_cmd_le = "${cmd1_le} && ${cmd2_le}"

  exec { "link-${name}-to-le":
  # The link-lets-encrypt-certs script returns 0 only when some
  # linking occurs.
  exec { "link-lets-encrypt-${name}":
    path    => '/usr/bin:/usr/sbin',
    command => $link_cmd_le,
    onlyif  => $onlyif_cmd_le,
    command => "echo 'linked certificates'",
    onlyif  => "/usr/sbin/link-lets-encrypt-certs $name",
    require => File['/usr/sbin/link-lets-encrypt-certs'],
  }

}