diff --git a/playbook/kdbox-deploy.yml b/playbook/kdbox-deploy.yml new file mode 100644 index 0000000000000000000000000000000000000000..9ffda4043731b069ca487db4f9ccac3ec3f26dd6 --- /dev/null +++ b/playbook/kdbox-deploy.yml @@ -0,0 +1,11 @@ +--- + +- name: a play that runs entirely on the ansible host + hosts: 127.0.0.1 + connection: local + vars_files: + - settings/kdbox.yml + + roles: + - kdbox + diff --git a/playbook/kdbox-playbook.yml b/playbook/kdbox-playbook.yml new file mode 100644 index 0000000000000000000000000000000000000000..8f5f7b22435086f7ed64acbbc3e35e9df8fcd58f --- /dev/null +++ b/playbook/kdbox-playbook.yml @@ -0,0 +1,76 @@ +--- + +- name: a play that runs entirely on the ansible host + hosts: 127.0.0.1 + connection: local + vars_files: + - settings/kdbox.yml + vars: + - interface_name: lo + - computer_name: noname + + vars_prompt: + - name: "re6sttoken" + prompt: "\n\n You are running the KDBox Installer\n\n + Please request a re6stnet token on https://slapos.vifib.com. \n\n + You will also need computer and account token, please get them on https://slapos.vifib.com. \n\n + A domain name will be required for kdbox slave frontend, to access erp5 later. \n\n + Enter your re6stnet token: " + + private: no + default: "notoken" + + - name: "slapos_master_url" + prompt: "What is the url to the SlapOS Master API? (ignore if you already have a configured re6st and slapos):" + private: no + default: "https://slap.vifib.com/" + + - name: "slapos_web_master_url" + prompt: "What is the url to the SlapOS Master Website? (ignore if you already have a configured re6st and slapos):" + private: no + default: "https://slapos.vifib.com/" + + - name: "computer_name" + prompt: "What is this computer name? (ignore if you already have a configured re6st and slapos):" + private: no + default: "noname" + + - name: "slapostoken" + prompt: "What is the server token ?:" + private: no + default: "notoken" + + - name: "Token" + prompt: "What is your credential account token" + private: no + default: "notoken" + + - name: "domain_name" + prompt: "Enter domain name for CDN main instance" + private: no + default: "kdbox.slapos-example.com" + + - name: "custom_domain" + prompt: "Enter custom domain name for CDN slave instance" + private: no + default: "" + + pre_tasks: + - file: path=/opt/kdbox state=directory mode=0755 + - copy: content="{{ domain_name }}" dest=/opt/kdbox/cdn_domain_name + when: + domain_name != "" + - copy: content="{{ custom_domain }}" dest=/opt/kdbox/cdn_custom_domain + when: + custom_domain != "" + + roles: + - re6stnet + - role: routeadv + # desactiver le RADVD + when: enable_router_advertisement == True + - { role: slapos, package_state: present } + - { role: package, package_name: ntp, package_state: present } + - slapos-client + - kdbox + diff --git a/playbook/roles/kdbox/files/challenge b/playbook/roles/kdbox/files/challenge new file mode 100755 index 0000000000000000000000000000000000000000..e62246175337848adbe946ea3a0ef5cf7526ebf6 --- /dev/null +++ b/playbook/roles/kdbox/files/challenge @@ -0,0 +1,11 @@ +#!/bin/bash + +domain=$1 +CODE=$(curl -s -n -k -L -o /dev/null -w "%{http_code}" "https://$domain/.well-known/manage_main") + +if [ "$CODE" == "200" ]; then + echo "Code=$CODE, .well-know exists already!" + exit 0 +else + curl -k -L -n -X POST -d "id=.well-known&submit=Add" http://$domain/portal_skins/custom/manage_addProduct/OFSP/manage_addFolder +fi diff --git a/playbook/roles/kdbox/files/kdbox-param b/playbook/roles/kdbox/files/kdbox-param new file mode 100755 index 0000000000000000000000000000000000000000..ab9725117a3cb0277ff05fb7b25b40d5f42321ae --- /dev/null +++ b/playbook/roles/kdbox/files/kdbox-param @@ -0,0 +1,38 @@ +#!/bin/bash + +if [ -z "$1" ]; then + echo "Argument 1 should be instance name and Argument 2 should be 'url' or 'pwd'" + exit 3 +fi + +for file in `grep -l -R "$1" /srv/slapgrid/slappart*/buildout*.cfg 2>/dev/null`; do + Folder=$(dirname $file) + # search runner0 partition + if [ -f "$Folder/bin/exporter" ]; then + PARTITION=$Folder + fi +done + +DB="$PARTITION/srv/runner/proxy.db" +if [ ! -f "$DB" ]; then + echo "ERP5 instance not ready" + exit 2 +fi + +# get parameters from database +DB_PARTITION_TABLE=$(sqlite3 $DB ".table partition__") +CONNECTION=$(sqlite3 $DB "select connection_xml from $DB_PARTITION_TABLE where reference='slappart0';") + +if [ -z "$CONNECTION" ]; then + echo "ERP5 instance not ready" + exit 1 +else + if [ "$2" == "pwd" ]; then + echo $CONNECTION | egrep -o 'inituser-password\"\:\s*\"[a-z,A-Z,0-9]+' | cut -d '"' -f 3 + elif [ "$2" == "url" ]; then + echo $CONNECTION | egrep -o 'family-default-v6\"\:\s*\"https\:\/\/\[.*\]:[0-9]+' | cut -d '"' -f 3 + else + echo "Argument 1 should be instance name and Argument 2 should be 'url' or 'pwd'" + exit 3 + fi +fi diff --git a/playbook/roles/kdbox/files/port-forwarding b/playbook/roles/kdbox/files/port-forwarding new file mode 100755 index 0000000000000000000000000000000000000000..2f6b27314660e55912e3f86b429a2b5623aa0576 --- /dev/null +++ b/playbook/roles/kdbox/files/port-forwarding @@ -0,0 +1,11 @@ +#!/bin/bash +ps aux | grep socat | grep TCP:$2:$3 > /dev/null +if [ $? -eq 0 ] +then + echo "port forwarding process already running" +else + echo "no process running ,executing port forwarding for selectet port" + socat TCP6-LISTEN:$1,fork TCP:$2:$3 & +fi + +#script for port forwarding diff --git a/playbook/roles/kdbox/meta/main.yml b/playbook/roles/kdbox/meta/main.yml new file mode 100644 index 0000000000000000000000000000000000000000..770f111cd5389767cfd6c76a154768f4bca74c61 --- /dev/null +++ b/playbook/roles/kdbox/meta/main.yml @@ -0,0 +1,15 @@ +--- +dependencies: + - role: package + package_name: socat + package_state: present + - role: package + package_name: sqlite3 + package_state: present + - role: package + package_name: curl + package_state: present + - role: package + package_name: git + package_state: present + diff --git a/playbook/roles/kdbox/tasks/dehydrated.yml b/playbook/roles/kdbox/tasks/dehydrated.yml new file mode 100644 index 0000000000000000000000000000000000000000..26c08d89b6030a2197f6225c9bf78e7dca4864b1 --- /dev/null +++ b/playbook/roles/kdbox/tasks/dehydrated.yml @@ -0,0 +1,45 @@ +--- + + - stat: path=/opt/kdbox/dehydrated + register: dehydrated + + - stat: path=/opt/kdbox/dehydrated/zope-hook.sh + register: hook_file + + - name: Get Dehydrated + shell: "git clone https://github.com/lukas2511/dehydrated.git /opt/kdbox/dehydrated" + when: dehydrated.stat.exists == False + + - copy: content="{{ custom_domain}}" dest=/opt/kdbox/dehydrated/domains.txt + + - template: src=config.j2 dest=/opt/kdbox/dehydrated/config mode=644 + + - name: Get Dehydrated zope hook + get_url: + url: https://lab.nexedi.com/nexedi/dehydrated-zope-hook/raw/master/zope-hook.sh + dest: /opt/kdbox/dehydrated/zope-hook.sh + mode: 0755 + when: hook_file.stat.exists == False + + - shell: "{{ role_path }}/files/kdbox-param '{{ webrunner_instance_name }}' pwd" + register: erp5_pwd + + - name: Add .netrc file + blockinfile: + dest: "~/.netrc" + mode: 0600 + create: yes + state: present + block: | + machine {{ custom_domain }} + login zope + password {{ erp5_pwd.stdout }} + + - stat: path="/opt/kdbox/dehydrated/certs/{{ custom_domain }}" + register: cert_folder + + - name: Get signed certificate for slave instance + shell: ./dehydrated -c --accept-terms + when: cert_folder.stat.exists == False + args: + chdir: /opt/kdbox/dehydrated diff --git a/playbook/roles/kdbox/tasks/deploy.yml b/playbook/roles/kdbox/tasks/deploy.yml new file mode 100644 index 0000000000000000000000000000000000000000..642cf0f454de8cb1817d80c3d776fdd9338ac63d --- /dev/null +++ b/playbook/roles/kdbox/tasks/deploy.yml @@ -0,0 +1,57 @@ +--- + + - stat: path=/opt/slapos.playbook/ + register: playbook_folder + + # temp part to use playbook from branch + - name: Download playbook + shell: git clone https://lab.nexedi.com/nexedi/slapos.package.git /tmp/kdbox-playbook + when: playbook_folder.stat.exists == False + + - shell: cd /tmp/kdbox-playbook/; git checkout alain-kdbox + when: playbook_folder.stat.exists == False + + - name: Copy slapos.playbook + shell: cp -ax /tmp/kdbox-playbook/playbook /opt/slapos.playbook/ + when: playbook_folder.stat.exists == False + + # part to use + #- name: Download the playbook + # shell: slapcache-download --destination=/opt/kdbox/archive.tar.gz + + #- name: Copy slapos.playbook + # unarchive: src=/opt/kdbox/archive.tar.gz dest=/opt/slapos.playbook + + - stat: path=/usr/local/bin/kdbox-deploy + register: bin_file + + - name: Set deploy script + copy: + content: "cd /opt/slapos.playbook; ansible-playbook kdbox-deploy.yml -i hosts --connection=local" + dest: /usr/local/bin/kdbox-deploy + mode: 0755 + when: bin_file.stat.exists == False + + - name: Remove kdbox deploy + file: path=/usr/local/bin/kdbox-deploy state=absent + when: kdbox_ok == True + + - name: Start deploy cron + cron: job="bash -lc /usr/local/bin/kdbox-deploy >> /var/log/kdbox.log 2>&1" + cron_file=ansible-kdbox-deploy + user="root" + name="Start kdbox deploy" + minute="*/1" + + - name: Remove cron task + cron: name="Start kdbox deploy" + cron_file=ansible-kdbox-deploy + state=absent + when: kdbox_ok == True + + - stat: path=/usr/local/bin/kdbox-state + register: kdbox_state + + - name: Add check state script + template: src=kdbox-state.j2 dest=/usr/local/bin/kdbox-state mode=755 + when: kdbox_state.stat.exists == False diff --git a/playbook/roles/kdbox/tasks/frontend-slave-instance.yml b/playbook/roles/kdbox/tasks/frontend-slave-instance.yml new file mode 100644 index 0000000000000000000000000000000000000000..cf3aa395e25d6ed44c9f7ecbaa138e64cd496bfc --- /dev/null +++ b/playbook/roles/kdbox/tasks/frontend-slave-instance.yml @@ -0,0 +1,33 @@ +--- + + # get ERP5 URL will fail if erp5 instance is not ready + - name: Get ERP5 backend URL + shell: "{{ role_path }}/files/kdbox-param '{{ webrunner_instance_name }}' url" + register: erp5_url + + - stat: path="/opt/kdbox/dehydrated/certs/{{ custom_domain }}" + register: cert_folder + + - name : requesting CDN slave instance for ERP5 + shell: echo "request('{{ frontend_software_release_url }}', '{{ custom_domain }}-slave',filter_kw={'computer_guid':'{{ computer_id }}'},partition_parameter_kw={'custom_domain':'{{ custom_domain }}','enable_cache':'true','type':'zope','url':'{{ erp5_url.stdout }}', 'path':'erp5/',},shared=True, software_type='custom-personal',)" | slapos console + when: cert_folder.stat.exists == False + register: request_slave + failed_when: "'error' in request_slave.stdout" + + - template: src=request-slave-frontend.j2 dest=/opt/kdbox/request_slave_frontend.py mode=644 + vars: + ssl_key_content: "{{ lookup('file', '/opt/kdbox/dehydrated/certs/{{ custom_domain }}/privkey.pem') }}" + ssl_crt_content: "{{ lookup('file', '/opt/kdbox/dehydrated/certs/{{ custom_domain }}/cert.pem') }}" + ssl_ca_crt_content: "{{ lookup('file', '/opt/kdbox/dehydrated/certs/{{ custom_domain }}/chain.pem') }}" + when: cert_folder.stat.exists == True + + - name: Update slave frontend certificate + shell: "cat /opt/kdbox/request_slave_frontend.py | slapos console" + register: output + when: cert_folder.stat.exists == True and kdbox_ok == False + failed_when: "'error' in output.stderr.lower()" + + - debug: msg="{{ output }}" + + - file: path=/opt/kdbox/kdbox_ok state=touch + when: cert_folder.stat.exists == True diff --git a/playbook/roles/kdbox/tasks/frontend.yml b/playbook/roles/kdbox/tasks/frontend.yml new file mode 100644 index 0000000000000000000000000000000000000000..869572ff3e677195683feed06e6c079241438c46 --- /dev/null +++ b/playbook/roles/kdbox/tasks/frontend.yml @@ -0,0 +1,24 @@ +--- + + - stat: path=/opt/kdbox/frontend_requested + register: frontend_requested + + - stat: path=/opt/kdbox/frontend_supplied + register: frontend_supplied + + - name: Caddy frontend supply + shell: slapos supply {{ frontend_software_release_url }} {{ computer_id }} + when: slapos_cfg.stat.exists == True and frontend_supplied.stat.exists == False + + - name: Frontend is supplied + file: path=/opt/kdbox/frontend_supplied state=touch + + - name: Requesting Caddy frontend instance + shell: echo "request('{{ frontend_software_release_url }}', '{{ frontend_instance_name }}', filter_kw={'computer_guid':'{{ computer_id}}'}, partition_parameter_kw={'-sla-1-computer_guid':'{{ computer_id }}','domain':'{{ domain_name }}','public-ipv4':'{{ ansible_default_ipv4.address }}',}, software_type='custom-personal',)" | slapos console + when: frontend_supplied.stat.exists == True and frontend_requested.stat.exists == False + register: output + failed_when: "'error' in output.stderr.lower()" + + - name: Frontend is requested + file: path=/opt/kdbox/frontend_requested state=touch + diff --git a/playbook/roles/kdbox/tasks/main.yml b/playbook/roles/kdbox/tasks/main.yml new file mode 100644 index 0000000000000000000000000000000000000000..e2219463cd3f2afadd707a9c3b4ebfda6e5c6536 --- /dev/null +++ b/playbook/roles/kdbox/tasks/main.yml @@ -0,0 +1,49 @@ +--- + + - file: path=/opt/kdbox state=directory mode=0755 + + - stat: path="/opt/kdbox/kdbox_ok" + register: kdbox_is_ok + + - name: register needed variables + set_fact: + computer_id: "{{ lookup('ini','computer_id section=slapos file=/etc/opt/slapos/slapos.cfg') }}" + domain_name: "{{ lookup('file', '/opt/kdbox/cdn_domain_name') }}" + custom_domain: "{{ lookup('file', '/opt/kdbox/cdn_custom_domain') }}" + kdbox_ok: "{{ kdbox_is_ok.stat.exists }}" + + - include: deploy.yml + + - name: Check if client configuration exists already + stat: path=/etc/opt/slapos/slapos.cfg + register: slapos_cfg + failed_when: slapos_cfg.stat.exists == False + + - name: check if request is done + stat: path=/opt/kdbox/request_is_done + register: request_done + + - include: webrunner.yml + - include: frontend.yml + - include: frontend-slave-instance.yml + + # find Caddy ip to be used for port forwarding + - name: Get Caddy local IP + shell: grep bind /srv/slapgrid/slappart*/etc/Caddyfile | cut -d ' ' -f4 | head -n1 + register: caddy_ip + failed_when: caddy_ip.stdout == "" + + # execute port-forwarding script in /files/port-forwarding + - name: "port 80 forwarding to {{ caddy_ip.stdout }}:8080" + shell: "{{ role_path }}/files/port-forwarding 80 {{ caddy_ip.stdout }} 8080" + register: forward_result + changed_when: forward_result.stdout != "port forwarding process already running" + + - name: "port 443 forwarding to {{ caddy_ip.stdout }}:4443" + shell: "{{ role_path }}/files/port-forwarding 443 {{ caddy_ip.stdout }} 4443" + register: forward_result + changed_when: forward_result.stdout != "port forwarding process already running" + + # generate signed certificate with letsencrypt + - include: dehydrated.yml + diff --git a/playbook/roles/kdbox/tasks/webrunner.yml b/playbook/roles/kdbox/tasks/webrunner.yml new file mode 100644 index 0000000000000000000000000000000000000000..a4122747821fda111d686a05f23e9a5a3ec43625 --- /dev/null +++ b/playbook/roles/kdbox/tasks/webrunner.yml @@ -0,0 +1,24 @@ +--- + + - stat: path=/opt/kdbox/webrunner_requested + register: webrunner_requested + + - stat: path=/opt/kdbox/webrunner_supplied + register: webrunner_supplied + + - name: webrunner supply + shell: slapos supply {{ webrunner_software_release_url }} {{ computer_id }} + when : slapos_cfg.stat.exists == True and webrunner_supplied.stat.exists == False + + - name: Webrunner is supplied + file: path=/opt/kdbox/webrunner_supplied state=touch + + - name: requesting webrunner instance + shell: echo "request('{{ webrunner_software_release_url }}', '{{ webrunner_instance_name }}', partition_parameter_kw={'-sla-runner0-computer_guid':'{{ computer_id }}','-sla-runner1-computer_guid':'{{ computer_id }}', 'auto-deploy':'true', 'auto-deploy-instance':'true', 'autorun':'true', 'slapos-software':'software/erp5',}, software_type='resilient',)" | slapos console + when: webrunner_supplied.stat.exists == True and webrunner_requested.stat.exists == False + failed_when: "'error' in output.stderr.lower()" + register: output + + - name: webrunner is requested + file: path=/opt/kdbox/webrunner_requested state=touch + when: output is defined diff --git a/playbook/roles/kdbox/templates/config.j2 b/playbook/roles/kdbox/templates/config.j2 new file mode 100644 index 0000000000000000000000000000000000000000..7bc73d60b9aecd3707087b402c182052546bb17a --- /dev/null +++ b/playbook/roles/kdbox/templates/config.j2 @@ -0,0 +1,3 @@ +WELLKNOWN="${BASEDIR}" +HOOK="${BASEDIR}/zope-hook.sh" +DOMAINS_TXT="${BASEDIR}/domains.txt" diff --git a/playbook/roles/kdbox/templates/kdbox-state.j2 b/playbook/roles/kdbox/templates/kdbox-state.j2 new file mode 100644 index 0000000000000000000000000000000000000000..afb1114fa2f28ccb06164c9364ccf4398678a68d --- /dev/null +++ b/playbook/roles/kdbox/templates/kdbox-state.j2 @@ -0,0 +1,12 @@ +#!/bin/bash + +PWD=$({{ role_path }}/files/kdbox-param '{{ webrunner_instance_name }}' pwd) + +if [ -z "$PWD" ]; then + echo "ERP5 KDBox is not ready yet!" + exit 1 +fi +echo "KDBOX is ready" +echo "URL: https://{{ custom_domain }}/" +echo "Init username: zope" +echo "Init password: $PWD" diff --git a/playbook/roles/kdbox/templates/request-slave-frontend.j2 b/playbook/roles/kdbox/templates/request-slave-frontend.j2 new file mode 100644 index 0000000000000000000000000000000000000000..3efbe9617797813fa3c29a7d556afb0110465d96 --- /dev/null +++ b/playbook/roles/kdbox/templates/request-slave-frontend.j2 @@ -0,0 +1,21 @@ +parameters = { + "custom_domain": "{{ custom_domain }}", + "enable_cache": "true", + "path": "erp5/", + "type": "zope", + "url": "{{ erp5_url.stdout }}", + "https-only": "true" +} + +parameters["ssl_key"] = """{{ ssl_key_content }}""" +parameters["ssl_crt"] = """{{ ssl_crt_content }}""" +parameters["ssl_ca_crt"] = """{{ ssl_ca_crt_content }}""" + +request( + "{{ frontend_software_release_url }}", + "{{ custom_domain }}-slave", + partition_parameter_kw=parameters, + shared=True, + software_type='custom-personal', + filter_kw={'computer_guid':'{{ computer_id }}'} +) diff --git a/playbook/roles/slapos-client/tasks/main.yml b/playbook/roles/slapos-client/tasks/main.yml new file mode 100644 index 0000000000000000000000000000000000000000..ac33b27a9fe20ba46afea190d0f56db85272b36f --- /dev/null +++ b/playbook/roles/slapos-client/tasks/main.yml @@ -0,0 +1,7 @@ +--- + - name: Check if client configuration exists already + stat: path=~/.slapos/slapos-client.cfg + register: client_cfg + - name: "install slapos client" + shell: slapos configure client --token {{Token}} + when : client_cfg.stat.exists == False and "{{Token}}" != "notoken" diff --git a/playbook/settings/kdbox.yml b/playbook/settings/kdbox.yml new file mode 100644 index 0000000000000000000000000000000000000000..5fea38ce5754bcf63eb5d0bdf1ea6e96b11cc76a --- /dev/null +++ b/playbook/settings/kdbox.yml @@ -0,0 +1,9 @@ +frontend_software_release_url: https://lab.node.vifib.com/nexedi/slapos/raw/1.0.95.2/software/caddy-frontend/software.cfg +re6st_annon: False +#variable crée pour desactiver le RADVD +enable_router_advertisement: False +re6st_fingerprint: sha256:499a44702d687e968c047d28e33f59e5c3bae71a38619dc730152a3557c20301 +re6st_registry_url: http://re6stnet.gnet.erp5.cn/ +webrunner_software_release_url: https://lab.nexedi.com/nexedi/slapos/raw/1.0.100/software/slaprunner/software.cfg +frontend_instance_name: kdbox-main-FRONTEND +webrunner_instance_name: kdbox-resilient-webrunner