diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ad5a6a9..a5fdeab 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -18,6 +18,7 @@ stages: - run-kubernetes - run-management-update - run-patchday + - run-hcloud-firewall lint-job: stage: lint @@ -363,3 +364,70 @@ run-patchday-prodwork01: +######## +### http://patorjk.com/software/taag/#p=display&f=Doom&t=patchday.yml +### +### _ _ _ __ _ _ _ _ +### | | | | | | / _(_) | | | | | +### | |__ ___| | ___ _ _ __| | | |_ _ _ __ _____ ____ _| | | _ _ _ __ ___ | | +### | '_ \ / __| |/ _ \| | | |/ _` | | _| | '__/ _ \ \ /\ / / _` | | || | | | '_ ` _ \| | +### | | | | (__| | (_) | |_| | (_| | | | | | | | __/\ V V / (_| | | || |_| | | | | | | | +### |_| |_|\___|_|\___/ \__,_|\__,_| |_| |_|_| \___| \_/\_/ \__,_|_|_(_)__, |_| |_| |_|_| +### ______ __/ | +### |______| |___/ +### + +.run-hcloud-firewall: + extends: .run-ansible + stage: run-hcloud-firewall + script: + - ansible-playbook -e "stage=${STAGE}" hcloud_firewall.yml --vault-password-file /tmp/vault-pass + after_script: + - rm /tmp/vault-pass + except: + - schedules + +run-hcloud-firewall-dev: + extends: .run-hcloud-firewall + resource_group: dev + before_script: + - export STAGE=dev + - echo "${ANSIBLE_VAULT_PASS_DEV}" > /tmp/vault-pass + only: + - main + +run-hcloud-firewall-devscr: + extends: .run-hcloud-firewall + resource_group: devscr + before_script: + - export STAGE=devscr + - echo "${ANSIBLE_VAULT_PASS_DEV}" > /tmp/vault-pass + only: + - main + +run-hcloud-firewall-qa: + extends: .run-hcloud-firewall + resource_group: qa + before_script: + - export STAGE=qa + - echo "${ANSIBLE_VAULT_PASS_QA}" > /tmp/vault-pass + only: + - qa + +run-hcloud-firewall-prodnso: + extends: .run-hcloud-firewall + resource_group: prodnso + before_script: + - export STAGE=prodnso + - echo "${ANSIBLE_VAULT_PASS_PRODNSO}" > /tmp/vault-pass + only: + - prodnso + +run-hcloud-firewall-prodwork01: + extends: .run-hcloud-firewall + resource_group: prodwork01 + before_script: + - export STAGE=prodwork01 + - echo "${ANSIBLE_VAULT_PASS_PRODWORK01}" > /tmp/vault-pass + only: + - prodnso diff --git a/group_vars/all/firewall.yml b/group_vars/all/firewall.yml index f07b746..ec451be 100644 --- a/group_vars/all/firewall.yml +++ b/group_vars/all/firewall.yml @@ -119,7 +119,7 @@ hcloud_firewall_objects_awx: - type: label_selector label_selector: - selector: 'stage={{ stage }},service=awx' + selector: 'stage={{ stage }},service' hcloud_firewall_objects_backup: - diff --git a/group_vars/stage_prodwork01/firewall.yml b/group_vars/stage_prodwork01/firewall.yml new file mode 100644 index 0000000..9a9d8d9 --- /dev/null +++ b/group_vars/stage_prodwork01/firewall.yml @@ -0,0 +1,53 @@ +--- +hcloud_firewall_objects: + - + name: "{{ stage }}-default" + state: present + rules: + - + direction: in + protocol: icmp + port: '' + source_ips: '{{ ip_whitelist }}' + destination_ips: [] + description: ICMP allowed + - + direction: in + protocol: tcp + port: '22' + source_ips: '{{ ip_whitelist }}' + destination_ips: [] + description: SSH allowed + - + direction: in + protocol: tcp + port: '80' + source_ips: '{{ ip_whitelist }}' + destination_ips: [] + description: HTTP allowed + - + direction: in + protocol: tcp + port: '443' + source_ips: '{{ ip_whitelist }}' + destination_ips: [] + description: HTTPS allowed + - + direction: in + protocol: tcp + port: 'any' + source_ips: '{{ ip_whitelist_admins }}' + destination_ips: [] + description: TCP - allow work from home without VPN + - + direction: in + protocol: udp + port: 'any' + source_ips: '{{ ip_whitelist_admins }}' + destination_ips: [] + description: UDP - allow work from home without VPN + apply_to: + - + type: label_selector + label_selector: + selector: 'stage={{ stage }}' diff --git a/group_vars/stage_prodwork01/plain.yml b/group_vars/stage_prodwork01/plain.yml index 5852779..c5f541a 100644 --- a/group_vars/stage_prodwork01/plain.yml +++ b/group_vars/stage_prodwork01/plain.yml @@ -1,6 +1,7 @@ --- stage: "prodwork01" +hcloud_firewall_app_specific_stuff: False default_plattform_users: - 'friedrich.goerz' @@ -11,7 +12,7 @@ default_plattform_users: - '{{ gitlab_ansible_user_name }}' # TODO read configuration with hetzner rest api -shared_service_network: "10.1.0.0/16" +shared_service_network: "10.3.0.0/16" shared_service_kube_cpl_01: "{{ stage_server_infos | selectattr('name', 'match', stage + '-kube-cpl-01' ) | map(attribute='private_ip') @@ -103,4 +104,4 @@ kubernetes_with_certmanager: False kubernetes_with_extdns: False kubernetes_with_ingress: False kubernetes_with_awx: False -kubernetes_with_gitea: False \ No newline at end of file +kubernetes_with_gitea: False diff --git a/roles/hcloud/tasks/configure-firewall2.yml b/roles/hcloud/tasks/configure-firewall2.yml index d32bd32..f22c031 100644 --- a/roles/hcloud/tasks/configure-firewall2.yml +++ b/roles/hcloud/tasks/configure-firewall2.yml @@ -22,47 +22,46 @@ - name: "BLOCK << WITHOUT >> pagination" block: - - name: "Get firewall object from list" - set_fact: - lookup_fw_obj: "{{ hcloud_firewalls_all.json.firewalls | community.general.json_query(jsonquery_find_firewall_name) }}" - vars: - jsonquery_find_firewall_name: "[?name=='{{ firewall_object.name }}']" + - name: "Get firewall object from list" + set_fact: + lookup_fw_obj: "{{ hcloud_firewalls_all.json.firewalls | community.general.json_query(jsonquery_find_firewall_name) }}" + vars: + jsonquery_find_firewall_name: "[?name=='{{ firewall_object.name }}']" when: - total_server_pages == '1' - name: "<< WITH >> pagination" block: - - name: "Get all existing firewalls" - uri: - method: GET - url: "https://api.hetzner.cloud/v1/firewalls?page={{ item }}" - body_format: json - headers: - accept: application/json - authorization: Bearer {{ hetzner_authentication_ansible }} - status_code: [200] - register: hcloud_firewalls_all - delegate_to: 127.0.0.1 - become: false - - - name: "Get firewall object from list" - set_fact: - lookup_fw_obj: "{{ hcloud_firewalls_all.json.results | community.general.json_query(querystr1) | first | community.general.json_query(querystr2) | community.general.json_query(querystr2) }}" - vars: - querystr1: "[[*].json.firewalls]" - querystr2: "[?name=='{{ firewall_object.name }}']" + - name: "Get all existing firewalls" + uri: + method: GET + url: "https://api.hetzner.cloud/v1/firewalls?page={{ item }}" + body_format: json + headers: + accept: application/json + authorization: Bearer {{ hetzner_authentication_ansible }} + status_code: [200] + register: hcloud_firewalls_all + delegate_to: 127.0.0.1 + become: false + + - name: "Get firewall object from list" + set_fact: + lookup_fw_obj: "{{ hcloud_firewalls_all.json.results | community.general.json_query(querystr1) | first | community.general.json_query(querystr2) | community.general.json_query(querystr2) }}" + vars: + querystr1: "[[*].json.firewalls]" + querystr2: "[?name=='{{ firewall_object.name }}']" when: - total_server_pages != '1' - - name: "Create firewall rule for <<{{ firewall_object.name }}>>" uri: method: POST url: "https://api.hetzner.cloud/v1/firewalls" body_format: json headers: - Content-Type: application/json + Content-Type: application/json authorization: Bearer {{ hetzner_authentication_ansible }} body: "{{ firewall_object | to_json }}" return_content: yes @@ -71,64 +70,114 @@ become: false when: - firewall_object.state == 'present' - - lookup_fw_obj | length == 0 + - lookup_fw_obj | length == 0 - name: "Update firewall rule for <<{{ firewall_object.name }}>>" - uri: - method: PUT - url: "https://api.hetzner.cloud/v1/firewalls/{{ lookup_fw_obj.0.id }}" - body_format: json - headers: - Content-Type: application/json - authorization: Bearer {{ hetzner_authentication_ansible }} - body: "{{ firewall_object | to_json }}" - return_content: yes - status_code: [200] - delegate_to: 127.0.0.1 - become: false + block: + + - name: "Step_1: update FW rule <<{{ firewall_object.name }}>>" + uri: + method: PUT + url: "https://api.hetzner.cloud/v1/firewalls/{{ lookup_fw_obj.0.id }}" + body_format: json + headers: + Content-Type: application/json + authorization: Bearer {{ hetzner_authentication_ansible }} + body: "{{ firewall_object | to_json }}" + return_content: yes + status_code: [200] + register: fw_update_step1 + delegate_to: 127.0.0.1 + become: false + + - name: "Setting VAR" + set_fact: + rules_obj: + rules: "{{ firewall_object.rules }}" + applyto_obj: + apply_to: "{{ firewall_object.apply_to }}" + + - name: "Step_2: update FW rule - update rules" + uri: + method: POST + url: "https://api.hetzner.cloud/v1/firewalls/{{ lookup_fw_obj.0.id }}/actions/set_rules" + body_format: json + headers: + Content-Type: application/json + authorization: Bearer {{ hetzner_authentication_ansible }} + body: "{{ rules_obj | to_json }}" + return_content: yes + status_code: [201] + register: fw_update_step2 + delegate_to: 127.0.0.1 + become: false + + - name: "Step_3: update FW rule - apply-to-resources" + uri: + method: POST + url: "https://api.hetzner.cloud/v1/firewalls/{{ lookup_fw_obj.0.id }}/actions/apply_to_resources" + body_format: json + headers: + Content-Type: application/json + authorization: Bearer {{ hetzner_authentication_ansible }} + body: "{{ applyto_obj | to_json }}" + return_content: yes + status_code: [201] + register: fw_update_step2 + delegate_to: 127.0.0.1 + become: false + + rescue: + - name: "Rescueing FW-apply-to part " + debug: + msg: "Everything fine - FW-apply-to part already applied" + when: + - fw_update_step2.status in [422] + - fw_update_step2.json.error.code == 'firewall_already_applied' + when: - firewall_object.state == 'present' - - lookup_fw_obj | length > 0 + - lookup_fw_obj | length > 0 - name: "Delete firewall rule for <<{{ firewall_object.name }}>>" block: - - name: "Create firewall object for deactivation" - set_fact: - deactivate_fw_obj: - remove_from: "{{ firewall_object.apply_to }}" - - - name: "Step_1: Unset usage of firewall rule <<{{ firewall_object.name }}>>" - uri: - method: POST - url: "https://api.hetzner.cloud/v1/firewalls/{{ lookup_fw_obj.0.id }}/actions/remove_from_resources" - body_format: json - headers: - Content-Type: application/json - authorization: Bearer {{ hetzner_authentication_ansible }} - body: "{{ deactivate_fw_obj | to_json }}" - return_content: yes - status_code: [201] - delegate_to: 127.0.0.1 - become: false - - - name: "Step_2: Delete firewall rule for <<{{ firewall_object.name }}>>" - uri: - method: DELETE - url: "https://api.hetzner.cloud/v1/firewalls/{{ lookup_fw_obj.0.id }}" - body_format: json - headers: - Content-Type: application/json - authorization: Bearer {{ hetzner_authentication_ansible }} - return_content: yes - status_code: [204] - register: cleanup_firewall - delegate_to: 127.0.0.1 - become: false - until: cleanup_firewall.status in [204] - retries: 15 - delay: 10 + - name: "Create firewall object for deactivation" + set_fact: + deactivate_fw_obj: + remove_from: "{{ firewall_object.apply_to }}" + + - name: "Step_1: Unset usage of firewall rule <<{{ firewall_object.name }}>>" + uri: + method: POST + url: "https://api.hetzner.cloud/v1/firewalls/{{ lookup_fw_obj.0.id }}/actions/remove_from_resources" + body_format: json + headers: + Content-Type: application/json + authorization: Bearer {{ hetzner_authentication_ansible }} + body: "{{ deactivate_fw_obj | to_json }}" + return_content: yes + status_code: [201] + delegate_to: 127.0.0.1 + become: false + + - name: "Step_2: Delete firewall rule for <<{{ firewall_object.name }}>>" + uri: + method: DELETE + url: "https://api.hetzner.cloud/v1/firewalls/{{ lookup_fw_obj.0.id }}" + body_format: json + headers: + Content-Type: application/json + authorization: Bearer {{ hetzner_authentication_ansible }} + return_content: yes + status_code: [204] + register: cleanup_firewall + delegate_to: 127.0.0.1 + become: false + until: cleanup_firewall.status in [204] + retries: 15 + delay: 10 when: - firewall_object.state == 'absent' - - lookup_fw_obj | length > 0 + - lookup_fw_obj | length > 0