diff --git a/group_vars/nextcloud.yml b/group_vars/nextcloud.yml index 20f295d..a4a43c5 100644 --- a/group_vars/nextcloud.yml +++ b/group_vars/nextcloud.yml @@ -1,11 +1,5 @@ nextcloud_server_name: nextcloud.pyrocufflink.net apache_server_name: '{{ nextcloud_server_name }}' -pg_hba_extra: -- type: host - database: nextcloud - user: nextcloud - address: ::1/128 - method: md5 nextcloud_trusted_proxies: - 127.0.0.1 - ::1 @@ -20,5 +14,4 @@ nextcloud_smtp: port: 25 dnf_automatic_exclude: nextcloud -postgresql_config_dir: /var/lib/pgsql/data -postgresql_allow_remote: false +nextcloud_db_host: postgresql.pyrocufflink.blue;sslcert=/etc/nextcloud/postgresql.cer;sslkey=/etc/nextcloud/postgresql.key;sslrootcert=system;sslmode=verify-full diff --git a/group_vars/postgresql.yml b/group_vars/postgresql.yml index 53db40b..eb80182 100644 --- a/group_vars/postgresql.yml +++ b/group_vars/postgresql.yml @@ -33,6 +33,11 @@ pg_hba_extra: user: all address: 0.0.0.0/0 method: cert +- type: hostssl + database: sameuser + user: all + address: '::/0' + method: cert postgresql_restore_command: >- runuser -u postgres -- diff --git a/hosts b/hosts index fc17525..a8b5bf4 100644 --- a/hosts +++ b/hosts @@ -113,6 +113,9 @@ vmhost1.pyrocufflink.blue [nextcloud] cloud0.pyrocufflink.blue +[nextcloud-db] +db0.pyrocufflink.blue + [ntpd] [nut-monitor:children] diff --git a/nextcloud.yml b/nextcloud.yml index e9737b1..1f02ed9 100644 --- a/nextcloud.yml +++ b/nextcloud.yml @@ -1,7 +1,16 @@ +- hosts: nextcloud-db + vars_files: + - vault/nextcloud + roles: + - role: nextcloud-db + tags: + - nextcloud-db + - hosts: nextcloud vars_files: - vault/nextcloud roles: - - postgresql-server - apache + - role: nextcloud-db-cert + tags: nextcloud-db-cert - nextcloud diff --git a/roles/nextcloud-base/defaults/main.yml b/roles/nextcloud-base/defaults/main.yml new file mode 100644 index 0000000..0669852 --- /dev/null +++ b/roles/nextcloud-base/defaults/main.yml @@ -0,0 +1,4 @@ +nextcloud_db_name: nextcloud +nextcloud_db_host: localhost +nextcloud_db_port: '' +nextcloud_db_user: nextcloud diff --git a/roles/nextcloud-base/tasks/main.yml b/roles/nextcloud-base/tasks/main.yml new file mode 100644 index 0000000..e69de29 diff --git a/roles/nextcloud-db-cert/files/fetch-cert.py b/roles/nextcloud-db-cert/files/fetch-cert.py new file mode 100644 index 0000000..c92ab0c --- /dev/null +++ b/roles/nextcloud-db-cert/files/fetch-cert.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python3 +import base64 +import json +import logging +import os +import ssl +import urllib.error +import urllib.request +from pathlib import Path + +try: + from systemd.journal import JournalHandler as LogHandler +except ModuleNotFoundError: + LogHandler = logging.StreamHandler + + +log = logging.getLogger('fetchcert') + + +CREDENTIALS_DIRECTORY = Path(os.environ['CREDENTIALS_DIRECTORY']) + +CA_FILE = Path('/etc/pki/ca-trust/kube-root-ca.crt') +CERT_OUT = Path('/etc/nextcloud/postgresql.cer') +KEY_OUT = Path('/etc/nextcloud/postgresql.key') + +BASE_URL = 'https://kubernetes.pyrocufflink.blue:6443' +NAMESPACE = 'postgresql-ca' +SECRET = 'nextcloud-client' + + +def main(): + if 'LOG_LEVEL' in os.environ: + logging.root.setLevel(os.environ['LOG_LEVEL'].upper()) + logging.root.addHandler(LogHandler()) + + token_path = CREDENTIALS_DIRECTORY / 'nextcloud.fetchcert.token' + log.debug('Reading token from %s', token_path) + token = token_path.read_text().rstrip() + + ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + ctx.load_verify_locations(cafile=CA_FILE) + + url = f'{BASE_URL}/api/v1/namespaces/{NAMESPACE}/secrets/{SECRET}' + headers = { + 'Authorization': f'Bearer {token}' + } + req = urllib.request.Request(url, headers=headers) + log.info('Fetching Secret from %s', url) + try: + res = urllib.request.urlopen(req, context=ctx) + except urllib.error.HTTPError as e: + log.error('%s %s', e, e.read()) + raise SystemExit(1) + with res: + body = json.load(res) + log.info('Received HTTP reponse %d %s', res.status, res.reason) + cert = base64.b64decode(body['data']['tls.crt'].encode('ascii')) + key = base64.b64decode(body['data']['tls.key'].encode('ascii')) + cert_new = CERT_OUT.with_suffix(f'{CERT_OUT.suffix}.new') + key_new = KEY_OUT.with_suffix(f'{KEY_OUT.suffix}.new') + if not CERT_OUT.exists() or CERT_OUT.read_bytes() != cert: + log.debug('Writing certificate to %s', cert_new) + with cert_new.open('wb') as f: + os.fchown(f.fileno(), 0, 48) + os.fchmod(f.fileno(), 0o0444) + f.write(cert) + if not KEY_OUT.exists() or KEY_OUT.read_bytes() != key: + log.debug('Writing private key to %s', key_new) + with key_new.open('wb') as f: + os.fchown(f.fileno(), 0, 48) + os.fchmod(f.fileno(), 0o0440) + f.write(key) + if cert_new.exists(): + log.debug('Renaming %s to %s', cert_new, CERT_OUT) + cert_new.rename(CERT_OUT) + if key_new.exists(): + log.debug('Renaming %s to %s', key_new, KEY_OUT) + key_new.rename(KEY_OUT) + log.info('Successfully fetched certificate from Kubernetes Secret') + + +if __name__ == '__main__': + main() diff --git a/roles/nextcloud-db-cert/files/nextcloud-fetch-cert.service b/roles/nextcloud-db-cert/files/nextcloud-fetch-cert.service new file mode 100644 index 0000000..0e8f7af --- /dev/null +++ b/roles/nextcloud-db-cert/files/nextcloud-fetch-cert.service @@ -0,0 +1,17 @@ +[Unit] +Description=Fetch Nextcloud database client certificate +Wants=network-online.target +After=network-online.target + +[Service] +Type=oneshot +Environment=LOG_LEVEL=debug +ExecStart=/usr/local/libexec/nextcloud-fetch-cert.py +LoadCredential=nextcloud.fetchcert.token +CapabilityBoundingSet=CAP_DAC_OVERRIDE CAP_CHOWN +PrivateTmp=yes +ProtectHome=yes +ProtectKernelTunables=yes +ProtectProc=invisible +ProtectSystem=full +ReadWritePaths=/etc/nextcloud diff --git a/roles/nextcloud-db-cert/handlers/main.yml b/roles/nextcloud-db-cert/handlers/main.yml new file mode 100644 index 0000000..c54df98 --- /dev/null +++ b/roles/nextcloud-db-cert/handlers/main.yml @@ -0,0 +1,8 @@ +- name: reload systemd + systemd: + daemon_reload: true + +- name: restart nextcloud-fetch-cert.timer + systemd: + name: nextcloud-fetch-cert.timer + state: restarted diff --git a/roles/nextcloud-db-cert/tasks/main.yml b/roles/nextcloud-db-cert/tasks/main.yml new file mode 100644 index 0000000..20d9a0d --- /dev/null +++ b/roles/nextcloud-db-cert/tasks/main.yml @@ -0,0 +1,71 @@ +- name: ensure nextcloud db cert fetch script is installed + copy: + src: fetch-cert.py + dest: /usr/local/libexec/nextcloud-fetch-cert.py + owner: root + group: root + mode: u=rwx,go=rx + notify: + - restart nextcloud-fetch-cert.timer + tags: + - copy-script + +- name: ensure nextcloud db cert fetch token credential exists + copy: + dest: /etc/credstore/nextcloud.fetchcert.token + content: |+ + {{ nextcloud_fetchcert_token }} + owner: root + group: root + mode: u=rw,go= + diff: false + tags: + - credentials + +- name: ensure kubernetes ca certificate is installed + copy: + src: kube-root-ca.crt + dest: /etc/pki/ca-trust/kube-root-ca.crt + owner: root + group: root + mode: u=rw,go=r + tags: + - cacert + +- name: ensure nextcloud cert fetch timer unit is installed + template: + src: nextcloud-fetch-cert.timer.j2 + dest: /etc/systemd/system/nextcloud-fetch-cert.timer + owner: root + group: root + mode: u=rw,go=r + notify: + - reload systemd + - restart nextcloud-fetch-cert.timer + tags: + - systemd +- name: ensure nextcloud cert fetch service unit is installed + copy: + src: nextcloud-fetch-cert.service + dest: /etc/systemd/system/nextcloud-fetch-cert.service + owner: root + group: root + mode: u=rw,go=r + notify: + - reload systemd + - restart nextcloud-fetch-cert.timer + tags: + - systemd + +- name: ensure nextcloud cert fetch timer is enabled + systemd: + name: nextcloud-fetch-cert.timer + enabled: true + tags: + - service +- name: ensure nextcloud cert fetch timer is started + systemd: + name: nextcloud-fetch-cert.timer + state: started + tags: + - service diff --git a/roles/nextcloud-db-cert/templates/nextcloud-fetch-cert.timer.j2 b/roles/nextcloud-db-cert/templates/nextcloud-fetch-cert.timer.j2 new file mode 100644 index 0000000..2e1b6db --- /dev/null +++ b/roles/nextcloud-db-cert/templates/nextcloud-fetch-cert.timer.j2 @@ -0,0 +1,9 @@ +[Unit] +Description=Periodically fetch Nextcloud database client certificate + +[Timer] +OnActiveSec=1s +OnUnitInactiveSec=12h + +[Install] +WantedBy=timers.target diff --git a/roles/nextcloud-db/meta/main.yml b/roles/nextcloud-db/meta/main.yml new file mode 100644 index 0000000..d6fc3f9 --- /dev/null +++ b/roles/nextcloud-db/meta/main.yml @@ -0,0 +1,2 @@ +dependencies: +- nextcloud-base diff --git a/roles/nextcloud-db/tasks/main.yml b/roles/nextcloud-db/tasks/main.yml new file mode 100644 index 0000000..5ed6083 --- /dev/null +++ b/roles/nextcloud-db/tasks/main.yml @@ -0,0 +1,19 @@ +- name: ensure nextcloud database user exists + become: true + become_user: postgres + postgresql_user: + name: '{{ nextcloud_db_user }}' + password: '{{ nextcloud_db_password|d(omit) }}' + state: present + tags: + - postgresql-user + +- name: ensure nextcloud database exists + become: true + become_user: postgres + postgresql_db: + name: nextcloud + owner: nextcloud + state: present + tags: + - postgresql-db diff --git a/roles/nextcloud/meta/main.yml b/roles/nextcloud/meta/main.yml index ff8645c..5804638 100644 --- a/roles/nextcloud/meta/main.yml +++ b/roles/nextcloud/meta/main.yml @@ -1,4 +1,5 @@ dependencies: +- nextcloud-base - role: redis tags: - redis diff --git a/roles/nextcloud/tasks/main.yml b/roles/nextcloud/tasks/main.yml index 213da0b..9bbb04e 100644 --- a/roles/nextcloud/tasks/main.yml +++ b/roles/nextcloud/tasks/main.yml @@ -27,21 +27,6 @@ tags: - always -- name: ensure nextcloud database user exists - become: true - become_user: postgres - postgresql_user: - name: nextcloud - password: '{{ nextcloud_db_password }}' - state: present -- name: ensure nextcloud database exists - become: true - become_user: postgres - postgresql_db: - name: nextcloud - owner: nextcloud - state: present - - name: ensure nextcloud is configured template: src: config.php.j2 diff --git a/roles/nextcloud/templates/config.php.j2 b/roles/nextcloud/templates/config.php.j2 index f3c3a68..094002f 100644 --- a/roles/nextcloud/templates/config.php.j2 +++ b/roles/nextcloud/templates/config.php.j2 @@ -37,12 +37,12 @@ $CONFIG = array ( 'dbtype' => 'pgsql', 'version' => '{{ nc_version }}', 'overwrite.cli.url' => 'https://{{ nextcloud_server_name }}', - 'dbname' => 'nextcloud', - 'dbhost' => 'localhost', - 'dbport' => '', + 'dbname' => '{{ nextcloud_db_name }}', + 'dbhost' => '{{ nextcloud_db_host }}', + 'dbport' => '{{ nextcloud_db_port }}', 'dbtableprefix' => 'oc_', - 'dbuser' => 'nextcloud', - 'dbpassword' => '{{ nextcloud_db_password }}', + 'dbuser' => '{{ nextcloud_db_user }}', + 'dbpassword' => '{{ nextcloud_db_password|d("") }}', 'installed' => true, 'ldapIgnoreNamingRules' => false, 'ldapProviderFactory' => 'OCA\\User_LDAP\\LDAPProviderFactory', diff --git a/roles/postgres-exporter/templates/postgres-exporter.container.j2 b/roles/postgres-exporter/templates/postgres-exporter.container.j2 index 0a0a681..d106bd9 100644 --- a/roles/postgres-exporter/templates/postgres-exporter.container.j2 +++ b/roles/postgres-exporter/templates/postgres-exporter.container.j2 @@ -6,7 +6,7 @@ After=postgresql.service [Container] Image=quay.io/prometheuscommunity/postgres-exporter:v0.15.0 -Environment=DATA_SOURCE_URI='postgres-exporter@:5432/template1?host=/run/postgresql' +Environment=DATA_SOURCE_URI='postgres-exporter@:5432/postgres?host=/run/postgresql' Mount=type=bind,source=/run/postgresql,target=/run/postgresql # container_t cannot access the PostgreSQL socket postgresql_var_run_t SecurityLabelDisable=true diff --git a/vault/minio/chromie.pyrocufflink.blue b/vault/minio/chromie.pyrocufflink.blue new file mode 100644 index 0000000..4bf03d0 --- /dev/null +++ b/vault/minio/chromie.pyrocufflink.blue @@ -0,0 +1,10 @@ +$ANSIBLE_VAULT;1.1;AES256 +30616536623331373031616465663933646439386165386266343530383461353463623631616630 +3739356666633732326464386630643135303335646431390a373532353964336464303930393665 +65336162663731376531336230306464326463396637656236396166646162613132626532393061 +6238336539636232300a653339363632363634656261616334333461313539333731386665383737 +34646336376630666166363962333036323763663166313166366432336165663434373534666333 +62346266623561333538613466643734393932396138386535636266336139623032343239653565 +31383862363362313432336638346265623439326363636363323961313430633938363461616530 +37313337333035343335323261323736343335393132376635303337623939303534353632643231 +61386332653533326463633165373032373635383135663230663066633039333736 diff --git a/vault/nextcloud b/vault/nextcloud index 761915c..b538f12 100644 --- a/vault/nextcloud +++ b/vault/nextcloud @@ -1,16 +1,65 @@ $ANSIBLE_VAULT;1.1;AES256 -33653661376330396337623339373036633836393966663639653965353633643639333861336333 -3631336266646164333837336432626361656133623834360a303534313436343764653133306466 -31313939623336373939633336656337316636323732646535386334343765623363366231306635 -6566333633613066660a333338373164663831396335643537333161343563373264343362333831 -30613533373166396437313565643132663231383233373363366662376132366238613863336561 -32373765643232653035633238643164636666363863313064393739313662356637306565326139 -38636466666136633561313534633531323338363565383036323366306237643463376331386231 -66313932663930366631306533386563636137656464656461356136396130336630306233313638 -33306138326465626561323836386266616438643834643338363232616530616532376431323565 -65383432656466616236386461343435383064643966373363373433346265666139633634323630 -63383130313132333434393636333733653236346265353063656563663462336139663465323931 -34653430393836633763396365393234323937373633313832636535333031316130656137323364 -39393962666131343461313336373061643037363338643332656162633438326539316635393839 -38663761366230393033373762343663386566326566383934316162353734623137393462623835 -316662656538353965626234306438356466 +35373862343534306138396561373666303964623562366139613363306639313437353463353730 +3233363232366137363764316331356336663933343731610a363566663933383162303231346138 +37653864626165666633386265633137316634666664613931663138646334653063363562363566 +6166633336666165380a306132356139396364653632386138346465633733356164376437656361 +64336564386138616465623937666565326232303062373430363966346636356665363936396339 +62623862653433616463316262393837353064613736626637396233306265613832643365393531 +35313337323431653234343361663766383065363865356161623731633239633465656134653165 +62333961393237376166623361636637346330313761303165316431353130656632653464386232 +30343433636334373263353762313738306131626439356363373632316634613835373563346232 +64313034386434653235623935363535623366393365626363393265353365386461383862653835 +37623732343234663635333665653065383561393632326263383364353135373935616630393836 +33323562303862326566356631613634323566626564663161613632303537643935616463633363 +64376530356338316132353361383536666539613531613638343864643966323362373730353061 +66303439376461303732393232323732383665633539306235303863363833346661373230366363 +66346164373330653636633735393938343537356231323366323134356138376336383461383731 +39613762653532303630363566376333376632343733656365386231326161303331383830393733 +61653237373239633566323864616138383832353563613835363135643736636361366238663932 +63623165316433613336363663623636313263356535356666663438376664333739323361636130 +30663036363763663835313933653238633437633830653165643563663933373333303337313732 +39653730353633383735353631333634303530326139336362356539393163386130656261633739 +33393066613665356239373163396263363733643164326339383137333439333866656566333862 +64616163336639313262666634333734633239663233316138646661356163346165306562663631 +33316164396331326463353264383266613062646463633634653163356661343766623031333736 +61333339613563613230663537383062643964366162313562393564656133643462393565623437 +36613165383635653330656130326564616637386334613635643230663264343036313236356265 +31343036613935323739653332346630363433353263306464303339653261373339376233663264 +32346463636535623032613333386238636461643066383533623963383332613936373139393363 +65666564353662363832326337396331663631313333306363636330343835656532653430383264 +36376235363162663964333338613765346638353730633130656432366236396432303730636137 +33306364656637663332343738343135343761663630633132363661316161346336343730393865 +63623335323633626161316537313562363737313036346438373463643865653636653739316337 +61663131366234383833346163356363643137666366333061323634366431653633386332613330 +65316266363866636663643830326138663035393730626332646531366666396566383736626363 +39643633363765353531323336626434396464383332383061336165366164663437386565616262 +32363738343937336430393132656136623838393865626632383061663565346564313939623563 +61356661386363303436376139316437666430353730383935626431396566353634363065633563 +30366465356363396632656661623439326538626233363632303963666231663539646139353865 +37633132643661616661313330653361363630303164333162313062646236366362336639396338 +66663864353763326163326466663237363131383330326135643265363739346361623939363131 +65373034313937663765326336383830356436333465663962393630623133363961653533363335 +34363034613465363238393739656361303833376264626333363464386461306437636430363863 +36306639313236663561663939656336363233306462333033386363363966646237633064623836 +63333562373839633964306362376230626436336134353730333135323862653436353566656436 +38666566383831623664633530663034343433636539613365663230353061633962323931306333 +33363863343664373661623265393938336163376139666465636433396333643336646236373861 +35653733626166396466396565313438366537643234313564303033396433363137626231303136 +36636237346631633237336361666564383131366134386232666538343965633438366661313662 +30336537646330623364643666633938383332323533333032356130343132363134333639646231 +62366631383739313330313566363565666230316636323565653334366665396334383431633730 +35626538306232303833656262346435383863383639383661666536356563396465653335323265 +34396530356437653862376164393133616663616162663038343731373561323636356338336361 +61613934333833353534643566663266356537336163353436383538646338343939336234636562 +63663664346433666639383664306232646136636235643337656161663664616234666437626461 +61343563656362663438613934386538346466373438633838303533343566326561313133303031 +37646262626139336265636230613230353035366363613138376166326261646136333038613265 +61373663653736376535353363323266383663303234316430386436376566636337353233336235 +36306162666630326666383235306562313264363562393464623839653566393531393830316666 +37366462626135353965306462313435373539336664346135643634303339306438613161636335 +32393663663731313865333733656166626265363463373936616635313234353132343036396539 +62643835376439323134303434616434313733633963656433303336396662343262626232313437 +39336364323030633935613534366430623761313762323164356263386132663364663631313535 +66663564623235373836393533376331363664666166313365313233373538316530626231383162 +34373331346136646236346533373137663832323263303439383331613034393433326363383237 +62643833343731313536