Add several roles; restructure group vars; restructure inventory.

all of this is required for the synology LE role to work. this is
still a massive WIP commit.

synology LE works, but synology webdav using that LE cert does not
yet work. there appears to be some cipher mismatch issue by default.
master
josiah 3 years ago
parent b2bf23dc9c
commit 7b7284c32f

@ -0,0 +1,19 @@
---
- name: Setup task server for ACME work.
hosts: larva.home.jowj.net
remote_user: "{{ remote_user }}"
roles:
- { name: acmedns_base, tags: ['acmedns_base'] }
- name: Setup synology to allow for remote cert copy
hosts: storage.home.jowj.net
remote_user: "{{ remote_user }}"
roles:
- { name: acmedns_remote_host, tags: ['acmedns_remote_host'] }
- name: Pull LE certs and copy them to Synology
hosts: larva.home.jowj.net
remote_user: "{{ remote_user }}"
roles:
- { name: acmedns_syno_updater, tags: ['acmedns_syno_updater'] }

@ -1,14 +1,18 @@
[defaults]
inventory = hosts.yml
inventory = inventory
pipelining = True
retry_files_enabled = False
stdout_callback = yaml
# stdout_callback = yaml
vault_password_file=open_the_vault.sh
ansible_python_interpreter=/usr/bin/python3
[ssh_connection]
scp_if_ssh = True
retries = 1
pipelining = True
[privilege_escalation]
become = True
[inventory]
enable_plugins = host_list, script, auto, yaml, ini, toml

@ -0,0 +1,24 @@
---
acmedns_remote_host_user: "{{ ansible_ssh_user }}"
acmedns_remote_host_ssh_client_pubkey: "{{ global_acmedns_ssh_client_pubkey }}"
# ACME DNS base updater settings
acmedns_base_certificate_dir: "/etc/acmedns/certificates"
acmedns_base_user: acmedns
acmedns_base_group: acmedns
acmedns_base_pubkey: "{{ global_acmedns_ssh_client_pubkey }}"
acmedns_base_privkey: "{{ vault_acmedns_base_privkey }}"
# ACME DNS Synology updater settings
acmedns_syno_updater_cert_base: "{{ acmedns_base_certificate_dir }}"
acmedns_syno_updater_user: "{{ acmedns_base_user }}"
acmedns_syno_updater_group: "{{ acmedns_base_group }}"
acmedns_syno_updater_job_name: storage
acmedns_syno_updater_email: admin@jowj.net
acmedns_syno_updater_domain: storage.home.jowj.net
acmedns_syno_updater_syn_user: josiah
acmedns_syno_updater_syn_server: "{{ acmedns_syno_updater_domain }}"
acmedns_syno_updater_syn_server_pubkey: storage.home.jowj.net,192.168.1.221 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNFlSCsoeS1dPFipdZYqr+WY38XRwQLsDds9BuOiRz8k1Palyief8QPxdBNAR28qyJb2QPjqEFlNQ1hHUt/+WTI=
acmedns_syno_updater_pubkey: "{{ global_acmedns_ssh_client_pubkey }}"
acmedns_syno_updater_privkey: "{{ acmedns_base_privkey }}"

@ -1,5 +1,7 @@
---
global_acmedns_ssh_client_pubkey: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJkuNfpGFXrTiIE4KU8jU57VltMiMXapDcDEd3vWQcEm acmedns@jowj.net
global_syslog_host: syslog.home.jowj.net
global_syslog_netsys_port: "514"
global_syslog_netcons_port: "5514"
@ -7,7 +9,7 @@ global_syslog_nettemp_port: "5515"
remote_user: josiah
gather_facts: True
source_os: arch
source_os: nixos
become: yes
create_user: josiah
ansible_become_pass: "{{ vault_ansible_become_pass }}"
@ -77,7 +79,6 @@ NEXTCLOUD_ADMIN_PASSWORD: "{{ VAULT_NEXTCLOUD_ADMIN_PASSWORD }}"
DO_AUTH_TOKEN: "{{ VAULT_DO_AUTH_TOKEN }}"
# Syslog shit
sysloghost_share_mountpoint: /syslog/
sysloghost_netsys_port: "{{ global_syslog_netsys_port }}"

@ -1,69 +1,91 @@
$ANSIBLE_VAULT;1.1;AES256
30353731373832343636383333326236373739643961303834373933393061353034633838646533
3563343663383134346435613861656265313737356639660a393636306532306533343933343934
66363537653637636264386362633162376366323263333162376462616430336639623662663336
3236376266356338650a366230363234353063383966333865616333663030653236323733613332
34393364633731613838623332313037353064616137356561363861353138366636633136356130
38393761356663383733323634623238343365643936366431623664626438383633626232363663
61623331663338323165323132343963663066313835346433323062613239646433653665663533
31306438306265653361313564623264656636316464343830313833306234373166623731363965
34353033343166323636373833653765383664336565346431373064613232633261363136316162
61646538353766393539623066333162353531656562306365313362393434643639346361363239
63623830626633653964393633306535313135396362663037353834376139323465356636663734
30616534653435393062666562653837623765666633613432616536353065333964383866613332
33333362663439316238313464376531303065386133643530356238306337656561623661633933
36346461346461356137313465396436626532613136376532623939646239326639663863663361
35326134666333653562346535623763396631336432666633616632333339656462663239393764
33643937363035633836376332623561336561386330346430363731326463313037323130306532
63613063633639386564363665326230663263316635363836396538613533393038613838653665
33333138373261646564623961616365363564333066646437613466393866663930626332346535
34653239363462626165353539363234343166313165366339356133666565666239626233626531
66323632346539313566336366346163333333633039356562333831303437333537323032633364
33636239613236626264623231643465316363656235393038306165613564633530386533643465
37396563636338313363346332313038646332336436633332623732386264393465393065353539
66383337656163653335363865333133353430333634666462616630303464326430353435623764
38643837613532393661316531373135323166396636626566346662616535316464396431373363
32393563666133363035323438616337613638666463616534633962356131633031626532353736
36353763363662363362393730386362636535356131383935623163323832653339343531333066
64343664646266313635306462383762366536346338626664626137623132653964636139373130
64363264656664373162306639356138636430383330643833663562313230363036373138313739
36363562316330333835323733383035623763656231316661646432623932633464313861383266
64616435616131383330663337613762326432363431356465396431356137356466633431303137
62366531633638383231393932353865326136663864353130626436663835333330373238643330
34653431343132353235333361333835313639653961313463346235626561613430366136356338
64663865396431336434346638623039333534353431373136623739653235323234323739323235
38393932386331643233343336613465336139343533623163306537356139303935623433616137
37656532613131333565666163623832633466353439303664623162313237323563373662316266
36386561316665636631356634396439653930613363396536653239373466303366336239316635
65333532326666376538613931613363623136653738333532323331616130373563383837363762
35646666653164393031306238343337656130623065386365636637393930363765343138313639
35373065366263663435343131626537336430366438663463333533326164396664393563363231
36326666636630643032663863663437656639613036643633666461613233313961646238333865
62313563376139396563313661643664643862326634653034636239316461343761653162626330
35343432363232386634343138336230616533613166646335363237313866376639646361306634
61386630366437326431646439383666653363373462656232616362626131323034656638313164
33323835303731346632636230613738643765623566366137643236396331323865313133623061
35616461373031663036373833376665636234656661386166323134306238626136613436383733
30666531313032393166356466386236323264373538383663303134613364666238653166363963
39366333383033626334623333363162613966356332366238613261316435313934346435663939
31636331646165356266626235616564386432343464663362393235373637333338653265633764
31636330353638313537366365623038366137646235383666343462633533363261633963623265
64393133636466616335333332326636383963306466356536343232336262363164636363333637
63343936616166656432343533343632663862646132643865316166353833373734303933343133
30383365616239646333646261396535613763646634663438393161623530663338626566333639
63393230373364333633663035396466326339353739656131323433663731333963633863636337
65633564386261343366663334356466663635313734356231326331653562383032656235643239
31386364313564323631353266656332626465383439626364646266663138326665383532626562
66303839643230396665333761353436333832303033343030313061306238613931633538616466
32393863363430653763396537393730633063656564346132323039663835666539326164623235
65663836613831333337396161653965643333646139343533633761303134353163383837326163
62343036396462643462323739613032653961303939656339383737323930326430636438303135
64613031376534326564633936656430396238656130343735343062386135643366363337346662
39356338306334333637373564323263613062356661333631623735316231353132626136613031
61636664323236656265616131613162636365303339386230346564376162616536636562633039
38373931326432643739623935393863316232626136393166323030353465336561643565656238
30393339616561306138646335633031646163666562333639633233653338393636653632323366
31656261666564303333633230643838636565383033326266633566343932383632383436633135
30353735613737383332663438623962626465336663303437313237623365396264643230373435
63316466393538636432643561613839663933363631356138646536626565373731386663326561
38356539613965316232
30643032326264646432303364373735613262346362643131633532373534613638343365323037
6538646464353734343265346639636266353436313461330a336337363134646163366133626330
37646530653363343130613964316463336230646435376632396366643231323266373462343535
3762333865303462640a333464666335323437643637313535666237323337313931326237633061
34306665396466306439623035393034346561336430653338303937343164363065333865393934
34346264373630643961643431663464666130376561373533346166666361643538373737313231
66376231623934313832313364666338303032303261613537373634616638616264333561396561
63646364386562613233303633333533393961363539383661633331383735663837616366626339
37396137353532393635666566656337303137326230313130633465343133653936623032356630
62346130323864306533653634643133393138316637633136666364383633663132623265353232
33633562643361363062613734356339366466656436643837376166353839393836653030343766
30356435626364323231336435613934353138313233393634353961323235616465656630303939
35376338656666396664636562616337336566336565366465383063373236366364393338653665
66623931633134303633623665653437376136643035653263343066616132383434636235346232
63326337613536656435373432383265666466656535643364396465396230613838343761646637
64643432333333313330656462656133663439333137353661353061613235656663373238613536
66663236373964343531643335323132376266363436316330333664633038343931633439633230
63306562363832656131346537383937373834356635383134353231363864363865363036616666
33633730316135303039633831373130343163633765656330363062656637646236646135393433
37636633623935306135303938356463616365346365646337623639393737646261346232633537
65623034383962336430353739373530626461653462393762343864373961653963313539396136
61363239333461353962356130656632363461373064306266356436323833303464353739396561
34346262653234333966363037303062393435333066363136643463313363376534663738323632
34363535386439353833343131633765343166336638663630313465613335393561343530373238
65633365303264306264626135363232653535373062666136383638623465666163363438333462
37363536393537323836646531323738636261303532653265653833653632346634346333306131
62656632383734663666613965386562313663373166336437343238393266383231643033643534
38356237356433356361633465396533626233326338303333646564366238383766343765393038
62373735363737633030636562346662356463353861653762663361356362323436313338333365
36653137356566613662326432636337626232383339393165343036376232333630346663646134
65333265353230303437663937373762366437616633306131363763633764626362613134636133
36376530363534373931343739626261633833353938613733336333383131313332613434306564
62663637643564313532383233636136323235363835313330323463303561663663656232346266
33383266313463373834353831333061316133633732653039343565323331323532626639363461
33383064666238383963306337316233646231316531313564616430663236653738636231333832
35643330303563323863343530636666633361393339653438646131333531666633366238643864
38306161666439353632633563343461353439396236343232333034346635313032306236653838
66383838386231366637646530643832386336623837316636376234316363386162316163343931
35366131653930353337346633383861366232316565613363653966613363396234383766623039
65666464373062333530373863333863343830316630306236626438393266346239613738343337
37653663373935333632383638306636366236326438313163626332343132303130316134316636
63306332646166393365386562396633313232616431646233336464363832333164383937653634
31363731613133393937346330653864666536663130346564623333316137373736386566613263
32313131363038323335346663336537333238333965633965333030363163656465396564643763
37643532356165316666383031353364336331343363346366356466333438326537343363646436
38363763333063636337613861643366313030383931663665303035396437373539366436616532
35313863356234343666353631663862646662393535666439343231663661353063643839353033
34366337613935336632363938616461376239363636626134333765393939643865376638353230
61633931333062313366383261363665396634343836373030313066333339373163646364363363
64323366373739383066643436666538366132613931393831326133366466626264313638373235
63373035323133303437353631656463626131346233353137333464633765323932303431373536
37306639386137353134613764623334626632326135303437643930663339353233623630633833
35373938633664666365646536313131626234333731663434383864656161623039393963336537
31616134336563353132623332386333373532366561373363383639653038383864323637323137
64343765663234346530353136333064613839666136303230376239663164333134316134613635
39333939656534643138343462326562653038306464653338653961656332623762663336393731
65343932656437646161643061616636613333383534363634663138376664306465643664363062
36393865366331653232326135633663623133313630663437376365306235613062303036363038
63353439666165306631346534376534643664653031326539343165616236653364323834613063
32353066353863346637316430616333316234396236356436623733653563366438363065646430
30393632666435636338656565343966323038386335316333373761666466633764613930333339
38633162393739613335373862393737383163623065396237623132616665666130633463663964
65373939323730336564303935323934646662356138356264633461316434383839373265373364
33356337306132393964393437396565383239323735626432353065626461393535363132336566
62623564616435613666303834656361396131653030626165386438623237313061613562356566
36343737623964373832353838366237373966623834666362643266303835633465646662633665
36316537633639376639336363363737353337373630363861383530663037386163313430643066
35333437366565636233356237303135306134333234303164313331663666343737393963646265
64643066663965323864383539656435383363663037323866363163306333356336326134633832
64316361396439393134663835353863303132663764653966316530303631333032336137356134
63353031326265663035336662623536346136666264363765613733626366353633613933373430
65663938633761646533626437303336666639643235316638366361323636633839666334653536
37303365366233353731306466333665643633343734663330356564303765646630353366306538
39646365616330346561646136666662376232313037613431636337306561626637393634386538
39323162653462303661333133633433333038383239333033396637356530636139353833383831
37366566363930396538636236613861396532656538323963636335316333623461653437643963
31313339393266383132353562343730353831333366303530613765353635643065656663323064
36346639343531346333346362343632613565303133626461383636646366303236636336643362
33623738663434396132386539626332623264306264303764393462346532356666643463303665
39363931383836356436393634353537326333306162626631646264393063346465336534323766
38623031323538323462626537343331663962656437656333373939653861343839393633666665
34356566333864343133636238343732363363653666376130383530303338313131343634646434
32653239643632373833613862326334656436393066343264613565623237646335663564653339
63316463663664346534386165386566393439306665393962333066323534646532643437343238
31313364626161356534646661353338366439623765643437336335366136313466653639363165
37326563356231346332393539353865626436633131306130333538613261656365366364366532
66666465646338373034343963333530373264343564373865396432353534333338363866353135
34636463643461356332633366623232303364323061626661323033643635376465326661376365
62623564653631363638393838383737323233643737316562396665336534316539303333313663
3737333935616530323134333861393639326631666234336539

@ -1,2 +1,3 @@
ansible_python_interpreter: /usr/bin/python3
interactive: yes
acmedns_base_lego_arch: arm64

@ -8,6 +8,7 @@ all:
hosts:
hatchery.home.jowj.net:
larva.home.jowj.net:
storage.home.jowj.net:
vpn:
hosts:
vpn.awful.club:

@ -1,4 +1,8 @@
* setup from scratch:
** install dependencies
ansible-galaxy collection install -r requirements.yml
** run a play
~ansible-playbook -i hosts.yml all.yml --ask-vault-pass --ask-become-pass~
** preparing open_the_vault

@ -0,0 +1,4 @@
---
collections:
- name: ansible.posix
- name: community.general

@ -0,0 +1,84 @@
---
- name: Install prereqs (debian)
apt:
name:
- python3-cryptography
state: latest
update_cache: yes
when: ansible_distribution == "Ubuntu"
- name: Add acme group
group:
name: "{{ acmedns_base_group }}"
system: yes
- name: Add acme user
user:
name: "{{ acmedns_base_user }}"
group: "{{ acmedns_base_group }}"
system: yes
create_home: yes
home: "{{ acmedns_base_home }}"
- name: Create acme user .ssh directory
file:
path: "{{ acmedns_base_home }}/.ssh"
state: directory
owner: "{{ acmedns_base_user }}"
group: "{{ acmedns_base_group }}"
mode: "0700"
- name: Create acme certificates directory
file:
path: "{{ acmedns_base_certificate_dir }}"
state: directory
owner: "{{ acmedns_base_user }}"
group: "{{ acmedns_base_group }}"
mode: "0700"
- name: Set acme user ssh key
copy:
content: "{{ item.value }}"
dest: "{{ acmedns_base_home }}/.ssh/{{ item.name }}"
owner: "{{ acmedns_base_user }}"
group: "{{ acmedns_base_group }}"
mode: "0600"
with_items:
- name: id_rsa
value: "{{ acmedns_base_privkey }}"
- name: id_rsa.pub
value: "{{ acmedns_base_pubkey }}"
no_log: yes
- name: Get lego
get_url:
url: "{{ acmedns_base_lego_uri }}"
dest: "{{ acmedns_base_lego_archive_path }}"
- name: Create lego extration dir
file:
state: directory
path: "{{ acmedns_base_lego_extracted_path }}"
owner: "{{ acmedns_base_user }}"
group: "{{ acmedns_base_group }}"
mode: "0755"
- name: Extract lego
unarchive:
src: "{{ acmedns_base_lego_archive_path }}"
dest: "{{ acmedns_base_lego_extracted_path }}"
remote_src: yes
- name: Install lego
file:
state: link
src: "{{ acmedns_base_lego_extracted_path }}/lego"
dest: /usr/local/bin/lego
- name: Install lego wrapper
template:
src: wraplego.py.j2
dest: /usr/local/bin/wraplego.py
owner: root
group: root
mode: "0755"

@ -0,0 +1,157 @@
#!/usr/bin/env python3
"""A wrapper for the lego commandline
Based on inflatable-wharf: https://github.com/mrled/inflatable-wharf
"""
import argparse
import datetime
import logging
import os
import subprocess
import sys
from cryptography import x509
from cryptography.hazmat.backends import default_backend
logging.basicConfig(
level=logging.INFO,
format='[%(asctime)s]\t%(levelname)s:\t%(message)s',
datefmt='%Y-%m-%d %H:%M:%S')
LOGGER = logging.getLogger(__name__)
def abswalk(path):
"""Return a list of absolute paths to files and directories
"""
result = []
for root, dirs, files in os.walk(path):
for dirname in dirs:
result.append(f"{os.path.join(root, dirname)}{os.path.sep}")
for filename in files:
result.append(f"{os.path.join(root, filename)}")
result.sort()
return result
def subprocess_run_log(command, env=os.environ.copy()):
"""Run and log a command
command A list making up a command and its arguments
env An optional dictionary of environment variables; defaults to this process's env
Returns the CompletedProcess object if the process exits with a zer return code
Throws subprocess.CalledProcessError if the process exites with a nonzero return code
"""
proc = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env)
LOGGER.debug("{cmdname} exited with code {rc}\n{out}\n{err}".format(
cmdname=command[0],
rc=proc.returncode,
out=f"STDOUT:\n{proc.stdout}" if proc.stdout else "STDOUT: NONE",
err=f"STDERR:\n{proc.stderr}" if proc.stderr else "STDERR: NONE"))
if proc.returncode != 0:
raise subprocess.CalledProcessError(
proc.returncode, command, output=proc.stdout, stderr=proc.stderr)
return proc
def get_cert_expiration(certificate):
"""Get the certificate expiration date as a DateTime object
"""
with open(certificate, 'rb') as certfile:
cert_contents = certfile.read()
cert = x509.load_pem_x509_certificate(cert_contents, default_backend())
return cert.not_valid_after
def shouldrun(certificate_path, min_cert_validity=25):
"""Test whether certificates should be requested/renewed
certificate Path to a certificate file
min_cert_validity If cert exists but is invalid this many days into the future, renew it
"""
try:
expires = get_cert_expiration(certificate_path)
expiresdelta = expires - datetime.datetime.now()
if expiresdelta.days <= min_cert_validity:
LOGGER.info(
"Determined lego should be run because the cert expires in "
f"{expiresdelta.days} days")
return True
else:
LOGGER.info(
"Determined lego should NOT be run because the cert expires in "
f"{expiresdelta.days} days")
return False
except FileNotFoundError:
LOGGER.info("Determined lego should be run because the cert does not exist locally")
return True
def certpath(legodir, domain, filetype):
"""Get the path of a cert file based on its characteristics
"""
result = os.path.join(legodir, "certificates", f"{domain}.{filetype}")
LOGGER.debug(f"certpath({legodir}, {domain}, {filetype}) => {result}")
return result
def lego(lego_dir, email, domain, authenticator, key_type=None, production=True, whatif=False):
"""Run the lego command.
whatif Do not actually run lego, but show what would have run
"""
command = [
'/usr/local/bin/lego', '--accept-tos',
'--path', lego_dir,
'--email', email,
'--domains', domain,
'--dns', authenticator,
'--dns-timeout', '60', # helped w 'could not determine authoritative nameservers' err
]
if not production:
command += ['--server', 'https://acme-staging-v02.api.letsencrypt.org/directory']
if key_type:
command += ['--key-type', key_type]
if os.path.exists(certpath(lego_dir, domain, 'crt')):
command += ["renew"]
else:
command += ["run"]
LOGGER.info("Running lego in {mode} mode as [{cmd}]".format(
mode="WHATIF" if whatif else "OPERATIONAL",
cmd=' '.join(command)))
if not whatif:
subprocess_run_log(command)
acme_dir_contents = '\n'.join(abswalk(lego_dir))
LOGGER.info(f"Current contents of {lego_dir}:\n{acme_dir_contents}")
def main(*args, **kwargs):
parser = argparse.ArgumentParser()
parser.add_argument("--legodir")
parser.add_argument("--email")
parser.add_argument("--domain")
parser.add_argument("--authenticator", default="route53")
parser.add_argument("--whatif", "-z", action="store_true")
parser.add_argument("--staging", action="store_true")
parser.add_argument("--renewdays", type=int, default=25)
parser.add_argument("--debug", "-d", action="store_true")
parser.add_argument("--key-type")
parser.add_argument("--verbose", "-v", action="store_true")
parsed = parser.parse_args()
if parsed.debug or parsed.verbose:
LOGGER.setLevel(logging.DEBUG)
if shouldrun(certpath(parsed.legodir, parsed.domain, 'crt'), min_cert_validity=parsed.renewdays):
lego(
parsed.legodir,
parsed.email,
parsed.domain,
parsed.authenticator,
key_type=parsed.key_type,
production=not parsed.staging,
whatif=parsed.whatif)
if __name__ == '__main__':
sys.exit(main(*sys.argv))

@ -0,0 +1,10 @@
---
acmedns_base_home: /home/{{ acmedns_base_user }}
acmedns_base_lego_version: 3.7.0
acmedns_base_lego_dir: lego_v{{ acmedns_base_lego_version }}_linux_{{ acmedns_base_lego_arch }}
acmedns_base_lego_archive: "{{ acmedns_base_lego_dir }}.tar.gz"
acmedns_base_lego_uri: https://github.com/go-acme/lego/releases/download/v{{ acmedns_base_lego_version }}/{{ acmedns_base_lego_archive }}
acmedns_base_lego_parent: /usr/local/src
acmedns_base_lego_archive_path: "{{ acmedns_base_lego_parent }}/{{ acmedns_base_lego_archive }}"
acmedns_base_lego_extracted_path: "{{ acmedns_base_lego_parent }}/{{ acmedns_base_lego_dir }}"

@ -0,0 +1,4 @@
---
acmedns_remote_host_fix_homedir_permissions: false
acmedns_remote_host_allow_passwordless_sudo: false

@ -0,0 +1,12 @@
# `acmedns_remote_host`
Set up a host so that an `acmedns_*_updater` role (which may run on another host) can copy certs to it.
This will include adding an ssh key to `authorized_keys`, and may include some other setup tasks.
Variables:
- `acmedns_remote_host_user`: The user on this host that will have the keys scp'd to it
- `acmedns_remote_host_ssh_client_pubkey`: The public key to add to `authorized_keys`
- `acmedns_remote_host_fix_homedir_permissions`: Modify homedir of `acmedns_remote_host_user` to not be world/group writable (required for ssh to allow key auth)
- `acmedns_remote_host_allow_passwordless_sudo`: Modify sudoers to allow `acmedns_remote_host_user` to sudo to root without providing a password

@ -0,0 +1,25 @@
---
- name: Fix homedir permissions
# SSH won't accept key auth if homedir is world/group writable, which it is by default on Synology
file:
path: "{{ lookup('env', 'HOME') }}"
mode: "0700"
state: directory
when: acmedns_remote_host_fix_homedir_permissions|bool
- name: Install SSH key
authorized_key:
user: "{{ acmedns_remote_host_user }}"
state: present
key: "{{ acmedns_remote_host_ssh_client_pubkey }}"
- name: Allow passwordless sudo
copy:
content: |+
{{ acmedns_remote_host_user }} ALL=(ALL) NOPASSWD: ALL
dest: /etc/sudoers.d/{{ acmedns_remote_host_user }}_passwordless
owner: root
group: root
mode: "0600"
when: acmedns_remote_host_allow_passwordless_sudo|bool

@ -0,0 +1,2 @@
---
acmedns_syno_updater_runonce: true

@ -0,0 +1,55 @@
---
- name: Add synology server to known_hosts
known_hosts:
name: "{{ acmedns_syno_updater_syn_server }}"
key: "{{ acmedns_syno_updater_syn_server_pubkey }}"
become: yes
become_user: "{{ acmedns_syno_updater_user }}"
- name: Install script
template:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
owner: root
group: "{{ acmedns_syno_updater_group }}"
mode: "0750"
with_items:
- src: acmedns_update.sh.j2
dest: "{{ acmedns_syno_updater_script_path }}"
- name: Configure cronvar
cronvar:
name: "{{ item.name }}"
value: "{{ item.value }}"
cron_file: "{{ acmedns_syno_updater_cron_file }}"
with_items:
- name: MAILTO
value: "{{ acmedns_syno_updater_email }}"
- name: Configure cronjob
cron:
name: "{{ acmedns_syno_updater_job_name }}"
day: "*"
hour: "3"
minute: "47"
job: "{{ acmedns_syno_updater_script_path }}"
user: "{{ acmedns_syno_updater_user }}"
cron_file: "{{ acmedns_syno_updater_cron_file }}"
- name: Run wrapper script once
# Wrapper script passes --days, so this won't contact Let's Encrypt unless necessary
command: "{{ acmedns_syno_updater_script_path }}"
become: yes
become_user: "{{ acmedns_syno_updater_user }}"
when: acmedns_syno_updater_runonce|bool
- name: Allow all users to run wrapper script as our user
lineinfile:
path: /etc/sudoers.d/acmedns_{{ acmedns_syno_updater_job_name }}
line: "ALL ALL=({{ acmedns_syno_updater_user }}) NOPASSWD: {{ acmedns_syno_updater_script_path }}"
owner: root
group: root
mode: "0640"
create: yes
validate: visudo -cf %s

@ -0,0 +1,14 @@
module acmedns_syno_updater_webhook_{{ acmedns_syno_updater_job_name }} 1.0;
require {
type user_home_t;
type sudo_exec_t;
type init_t;
class file { execute execute_no_trans map open read };
}
#============= init_t ==============
allow init_t sudo_exec_t:file { execute execute_no_trans map open read };
allow init_t user_home_t:file map;

@ -0,0 +1,51 @@
#!/bin/sh
set -eu
export DO_AUTH_TOKEN={{ DO_AUTH_TOKEN }}
echoexec() { echo "Running: $*"; $*; }
echoexec /usr/local/bin/wraplego.py \
--verbose \
--legodir "{{ acmedns_syno_updater_certificate_dir }}" \
--email "{{ acmedns_syno_updater_email }}" \
--domain "{{ acmedns_syno_updater_domain }}" \
--authenticator "digitalocean" \
host="{{ acmedns_syno_updater_syn_user }}@{{ acmedns_syno_updater_syn_server }}"
date=$(date +%Y%m%d)
tmppath=/tmp/${date}-acme-update
scp -r {{ acmedns_syno_updater_certificate_dir }}/certificates $host:$tmppath
user="josiah"
#
# SSH to the remote server and install the certs:
#
echo "$(cat <<ENDSSH
echo "$(cat <<ENDSUDO
echo 'Copying files...'
cd /usr/syno/etc/ssl
if ! test -d /usr/syno/etc/certificate.acme_renew_hook_backup; then
cp -r /usr/syno/etc/certificate /usr/syno/etc/certificate.acme_renew_hook_backup
fi
chown -R root:root "$tmppath"
mv $tmppath/{{ acmedns_syno_updater_domain }}.crt /usr/syno/etc/certificate/system/default/fullchain.pem
mv $tmppath/{{ acmedns_syno_updater_domain }}.key /usr/syno/etc/certificate/system/default/privkey.pem
# fix webdav shit
cp /usr/syno/etc/certificate/system/default/fullchain.pem /usr/local/etc/certificate/WebDAVServer/webdav/
cp /usr/syno/etc/certificate/system/default/privkey.pem /usr/local/etc/certificate/WebDAVServer/webdav/
# end fixing webdav shit
echo 'Removing temp dir...'
rm -rf $tmppath
echo 'Reloading webservers...'
sudo /usr/syno/sbin/synoservicecfg --reload nginx
/var/packages/WebDAVServer/scripts/start-stop-status stop
/var/packages/WebDAVServer/scripts/start-stop-status start
echo 'Done'
ENDSUDO
)" | sudo su -
ENDSSH
)" | ssh $host

@ -0,0 +1,10 @@
{
"id": "acmedns_{{ acmedns_syno_updater_job_name }}",
"execute-command": "sudo",
"pass-arguments-to-command": [
{"source": "string", "name": "-u"},
{"source": "string", "name": "{{ acmedns_syno_updater_user }}"},
{"source": "string", "name": "{{ acmedns_syno_updater_script_path }}"}
],
"include-command-output-in-response": true
}

@ -0,0 +1,6 @@
---
acmedns_syno_updater_cron_file: "acmedns_update_{{ acmedns_syno_updater_job_name }}"
acmedns_syno_updater_certificate_dir: "{{ acmedns_syno_updater_cert_base }}/{{ acmedns_syno_updater_job_name }}"
acmedns_syno_updater_renew_days: 20
acmedns_syno_updater_script_path: /usr/local/bin/acmedns_update_{{ acmedns_syno_updater_job_name }}.sh

@ -0,0 +1,56 @@
---
- name: Add synology server to known_hosts
known_hosts:
name: "{{ acmedns_syno_updater_syn_server }}"
key: "{{ acmedns_syno_updater_syn_server_pubkey }}"
become: yes
become_user: "{{ acmedns_syno_updater_user }}"
- name: Install script
template:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
owner: root
group: "{{ acmedns_syno_updater_group }}"
mode: "0750"
with_items:
- src: acmedns_update.sh.j2
dest: "{{ acmedns_syno_updater_script_path }}"
- name: Configure cronvar
cronvar:
name: "{{ item.name }}"
value: "{{ item.value }}"
cron_file: "{{ acmedns_syno_updater_cron_file }}"
with_items:
- name: MAILTO
value: "{{ acmedns_syno_updater_email }}"
- name: Configure cronjob
cron:
name: "{{ acmedns_syno_updater_job_name }}"
day: "*"
hour: "3"
minute: "47"
job: "{{ acmedns_syno_updater_script_path }}"
user: "{{ acmedns_syno_updater_user }}"
cron_file: "{{ acmedns_syno_updater_cron_file }}"
- name: Run wrapper script once
# Wrapper script passes --days, so this won't contact Let's Encrypt unless necessary
command: "{{ acmedns_syno_updater_script_path }}"
become: yes
become_user: "{{ acmedns_syno_updater_user }}"
when: acmedns_syno_updater_runonce|bool
- name: Allow all users to run wrapper script as our user
lineinfile:
path: /etc/sudoers.d/acmedns_{{ acmedns_syno_updater_job_name }}
line: "ALL ALL=({{ acmedns_syno_updater_user }}) NOPASSWD: {{ acmedns_syno_updater_script_path }}"
owner: root
group: root
mode: "0640"
create: yes
validate: visudo -cf %s

@ -0,0 +1,42 @@
#!/bin/sh
set -eu
export DO_AUTH_TOKEN={{ acmedns_syno_auth_token }}
echoexec() { echo "Running: $*"; $*; }
echoexec /usr/local/bin/wraplego.py \
--verbose \
--legodir "{{ acmedns_syno_updater_certificate_dir }}" \
--email "{{ acmedns_syno_updater_email }}" \
--domain "{{ acmedns_syno_updater_domain }}" \
--authenticator "digitalocean" \
host="{{ acmedns_syno_updater_syn_user }}@{{ acmedns_syno_updater_syn_server }}"
date=$(date +%Y%m%d)
tmppath=/tmp/${date}-acme-update
scp -r {{ acmedns_syno_updater_certificate_dir }}/certificates $host:$tmppath
#
# SSH to the remote server and install the certs:
#
echo "$(cat <<ENDSSH
echo "$(cat <<ENDSUDO
echo 'Copying files...'
cd /usr/syno/etc/ssl
if ! test -d /usr/syno/etc/certificate.acme_renew_hook_backup; then
cp -r /usr/syno/etc/certificate /usr/syno/etc/certificate.acme_renew_hook_backup
fi
chown -R root:root "$tmppath"
mv $tmppath/{{ acmedns_syno_updater_domain }}.crt /usr/syno/etc/certificate/system/default/fullchain.pem
mv $tmppath/{{ acmedns_syno_updater_domain }}.key /usr/syno/etc/certificate/system/default/privkey.pem
echo 'Removing temp dir...'
rm -rf $tmppath
echo 'Reloading webserver...'
sudo /usr/syno/sbin/synoservicecfg --reload nginx
echo 'Done'
ENDSUDO
)" | sudo su -
ENDSSH
)" | ssh $host
Loading…
Cancel
Save