From 54f09b059227de29efffa37ecf80ae12a0f708dd Mon Sep 17 00:00:00 2001 From: Philipp Gassmann Date: Fri, 4 Dec 2015 11:29:50 +0100 Subject: [PATCH] add firstrun_webroot mode, fix facts dir, add documentation --- manifests/exec/webroot.pp | 23 ++++++-- manifests/init.pp | 86 +++++++++++++++++----------- manifests/install.pp | 2 +- spec/defines/exec_standalone_spec.rb | 3 +- spec/defines/exec_webroot_spec.rb | 22 ++++++- templates/cli.ini.erb | 2 +- 6 files changed, 94 insertions(+), 44 deletions(-) diff --git a/manifests/exec/webroot.pp b/manifests/exec/webroot.pp index 57a29e2..bdef0ea 100644 --- a/manifests/exec/webroot.pp +++ b/manifests/exec/webroot.pp @@ -15,18 +15,33 @@ letsencrypt::exec::standalone{ $name: domains => $domains, server => $server, - } -> + } # TODO FIXME: This fails if webroot is defined multiple times - file{ '/etc/facts.d': ensure => directory; } - file{ '/etc/facts.d/letsencrypt.txt': + file{ ['/etc/facter', '/etc/facter/facts.d']: ensure => directory; } + file{ '/etc/facter/facts.d/letsencrypt.txt': content => 'letsencrypt_firstrun=SUCCESS', owner => root, group => root, mode => '0644', + require => Letsencrypt::Exec::Standalone[$name]; } } else { + if $letsencrypt::firstrun_webroot and $::letsencrypt_firstrun != 'SUCCESS'{ + $real_webroot = $letsencrypt::firstrun_webroot + # TODO FIXME: This fails if webroot is defined multiple times + file{ ['/etc/facter', '/etc/facter/facts.d']: ensure => directory; } + file{ '/etc/facter/facts.d/letsencrypt.txt': + content => 'letsencrypt_firstrun=SUCCESS', + owner => root, + group => root, + mode => '0644', + require => Exec["letsencrypt-exec-webroot-${name}"], + } + } else { + $real_webroot = $webroot + } exec{ "letsencrypt-exec-webroot-${name}": - command => "letsencrypt certonly -a webroot --webroot-path ${webroot} -d ${params_domain} --renew-by-default --server ${server}", + command => "letsencrypt certonly -a webroot --webroot-path ${real_webroot} -d ${params_domain} --renew-by-default --server ${server}", creates => "/etc/letsencrypt/live/${domains[0]}/fullchain.pem", require => File['/etc/letsencrypt/cli.ini']; } diff --git a/manifests/init.pp b/manifests/init.pp index 1594a4b..811659b 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -1,49 +1,72 @@ # Let's Encrypt # == Class: letsencrypt # -# Full description of class letsencrypt here. +# Let's Encrypt base configuration and hiera interface. # # === Parameters # -# Document parameters here. +# [*email*] +# Required, email-address for registration and key recovery # -# [*sample_parameter*] -# Explanation of what this parameter affects and what it defaults to. -# e.g. "Specify one or more upstream ntp servers as an array." +# [*agree_tos*] +# Required true, Please read the Terms of Service at +# https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf. +# You must agree in order to register with the ACME +# server at https://acme-v01.api.letsencrypt.org/directory # -# === Variables +# [*server*] +# ACME Server, defaults to staging instance. For Production use +# set it to 'https://acme-v01.api.letsencrypt.org/directory' # -# Here you should define a list of variables that this module would require. +# [*webroot*] +# This directory is configured as webroot for the webroot authentication +# locations added to the vhost to allow renewals # -# [*sample_variable*] -# Explanation of how this variable affects the funtion of this class and if -# it has a default. e.g. "The parameter enc_ntp_servers must be set by the -# External Node Classifier as a comma separated list of hostnames." (Note, -# global variables should be avoided in favor of class parameters as -# of Puppet 2.6.) +# [*firstrun_webroot*] +# Use different webroot on first run. +# Set this to the default webroot of the webserver if the service +# starts automatically when installed. +# E.g. Nginx on Ubuntu: /usr/share/nginx/html +# +# [*firstrun_standalone*] +# Use standalone mode on first run. +# Set this to true if the webserver does not start automatically when installed. +# letsencrypt will use standalone mode to get the certificate +# before the webserver is started the first time. +# +# [*rsa_key_size*], [*work_dir*], [*logs_dir*], +# Configruation options for letsencrypt cli.ini +# +# [*nginx_locations*], [*nginx_vhosts*], [*exec_standalone*], [*exec_webroot*] +# These Parameters can be used to create instances of these defined types through hiera # # === Examples # # class { 'letsencrypt': -# servers => [ 'pool.ntp.org', 'ntp.local.company.com' ], +# email => 'email@example.com', +# agree_tos => true +# firstrun_webroot => '/usr/share/nginx/html' +# nginx_vhosts => { +# 'mydomain.example.com' => {} +# } # } # # === Authors # -# Author Name +# Philipp Gassmann # # === Copyright # -# Copyright 2015 Your name here, unless otherwise noted. +# Copyright 2015 Philipp Gassmann here, unless otherwise noted. # class letsencrypt( $email, $agree_tos = false, + $server = 'https://acme-staging.api.letsencrypt.org/directory', # 'https://acme-v01.api.letsencrypt.org/directory', # $webroot = '/var/lib/letsencrypt/webroot', - $server = 'https://acme-v01.api.letsencrypt.org/directory', # https://acme-staging.api.letsencrypt.org/directory - $firstrun_standalone = true, + $firstrun_webroot = undef, # For Debian & Nginx: /usr/share/nginx/html + $firstrun_standalone = false, $rsa_key_size = '2048', - $config_dir = '/etc/letsencrypt', $work_dir = '/var/lib/letsencrypt', $logs_dir = '/var/log/letsencrypt', $nginx_locations = {}, @@ -55,24 +78,17 @@ unless $agree_tos { fail('letsencrypt: Please read the Terms of Service at https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf. You must agree in order to register with the ACME server at https://acme-v01.api.letsencrypt.org/directory') } - if $webroot == '/var/lib/letsencrypt/webroot' { - file{ [ - '/var/lib/letsencrypt', - '/var/lib/letsencrypt/webroot', - ]: - ensure => directory, - owner => root, - group => root, - mode => '0644'; - } + file{ [ + '/etc/letsencrypt', + '/var/lib/letsencrypt', + '/var/lib/letsencrypt/webroot', + ]: + ensure => directory, + owner => root, + group => root, + mode => '0644'; } - file{'/etc/letsencrypt': - ensure => directory, - owner => root, - group => root, - mode => '0644'; - } file{'/etc/letsencrypt/cli.ini': content => template('letsencrypt/cli.ini.erb'), owner => root, diff --git a/manifests/install.pp b/manifests/install.pp index b0f04d8..de506f3 100644 --- a/manifests/install.pp +++ b/manifests/install.pp @@ -21,7 +21,7 @@ } # Link does not work, create wrapper file{'/usr/local/bin/letsencrypt': - content => "#!/bin/bash\npushd /opt/letsencrypt/ \n ./letsencrypt-auto \"$@\" \npopd\n", + content => "#!/bin/bash\ncd /opt/letsencrypt/ \n ./letsencrypt-auto \"$@\" || exit 1 \n", owner => root, group => root, mode => '0750'; diff --git a/spec/defines/exec_standalone_spec.rb b/spec/defines/exec_standalone_spec.rb index e8714e4..09fa9f4 100644 --- a/spec/defines/exec_standalone_spec.rb +++ b/spec/defines/exec_standalone_spec.rb @@ -11,8 +11,9 @@ " Exec{ path => '/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin' } class{ 'letsencrypt': + email => 'admin@example.com', agree_tos => true, - email => 'admin@example.com'; + server => 'https://acme-v01.api.letsencrypt.org/directory', } " end diff --git a/spec/defines/exec_webroot_spec.rb b/spec/defines/exec_webroot_spec.rb index 2d7fb3e..2cceaab 100644 --- a/spec/defines/exec_webroot_spec.rb +++ b/spec/defines/exec_webroot_spec.rb @@ -11,8 +11,9 @@ " Exec{ path => '/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin' } class{ 'letsencrypt': + email => 'admin@example.com', agree_tos => true, - email => 'admin@example.com', + server => 'https://acme-v01.api.letsencrypt.org/directory', firstrun_standalone => false, } " @@ -65,7 +66,7 @@ :server => 'http://boulderx.example.com', )} end - context "with firstrun_standalone mode" do + context "with firstrun_standalone mode success" do let(:pre_condition) do " Exec{ path => '/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin' } @@ -86,4 +87,21 @@ it { should compile.with_all_deps } it { should contain_exec('letsencrypt-exec-webroot-foo.com')} end + context "with firstrun_webroot " do + let(:pre_condition) do + " + Exec{ path => '/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin' } + class{ 'letsencrypt': + agree_tos => true, + email => 'admin@example.com', + firstrun_webroot => '/firstrun-webroot', + } + " + end + let(:title) { 'foo.com' } + it { should compile.with_all_deps } + it { should contain_exec('letsencrypt-exec-webroot-foo.com').with( + :command => /--webroot-path \/firstrun-webroot/, + )} + end end diff --git a/templates/cli.ini.erb b/templates/cli.ini.erb index c4fbf1e..3bfbbce 100644 --- a/templates/cli.ini.erb +++ b/templates/cli.ini.erb @@ -23,7 +23,7 @@ text = True # authenticator = webroot webroot-path = <%= scope['webroot'] %> -config-dir = <%= scope['config_dir'] %> +config-dir = '/etc/letsencrypt' work-dir = <%= scope['work_dir'] %> logs-dir = <%= scope['logs_dir'] %>