forked from infra/ansible
Add Ansible playbook to toggle Koji HTTP access with nftables
Signed-off-by: Samyak Jain <samyak.jn11@gmail.com>
This commit is contained in:
parent
f2239cb238
commit
d9e7279830
1 changed files with 133 additions and 0 deletions
133
playbooks/manual/releng/koji-http-toggle.yml
Normal file
133
playbooks/manual/releng/koji-http-toggle.yml
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
---
|
||||
# Quick toggle for Koji HTTP access via nftables.
|
||||
# Run with: -e "koji_action=block|unblock|status" -e "koji_hosts=koji|koji_stg"
|
||||
# Optional: -e "koji_http_port_override=80"
|
||||
- name: Toggle Koji HTTP access using nftables
|
||||
hosts: "{{ koji_hosts | default('koji_stg:koji:koji_riscv') }}"
|
||||
user: root
|
||||
gather_facts: true
|
||||
|
||||
vars_files:
|
||||
- /srv/web/infra/ansible/vars/global.yml
|
||||
- "{{ private }}/vars.yml"
|
||||
- /srv/web/infra/ansible/vars/{{ ansible_distribution }}.yml
|
||||
|
||||
vars:
|
||||
koji_http_port: "{{ koji_http_port_override | default('80') }}"
|
||||
nft_table: "inet filter"
|
||||
nft_chain: "input"
|
||||
nft_set: "koji_http_block_src"
|
||||
nft_comment: "koji-http-block"
|
||||
is_staging: "{{ inventory_hostname in groups['koji_stg'] or inventory_hostname in groups.get('koji_stg_rdu3', []) }}"
|
||||
proxy_hostnames: "{{ is_staging | ternary(['proxy01.stg.rdu3.fedoraproject.org', 'proxy02.stg.rdu3.fedoraproject.org'], ['proxy01.rdu3.fedoraproject.org', 'proxy10.rdu3.fedoraproject.org']) }}"
|
||||
|
||||
pre_tasks:
|
||||
- name: Validate koji_action
|
||||
ansible.builtin.fail:
|
||||
msg: "Usage: -e 'koji_action=block|unblock|status'"
|
||||
when: koji_action is not defined or koji_action not in ['block', 'unblock', 'status']
|
||||
tags: always
|
||||
|
||||
tasks:
|
||||
- name: Resolve proxy IPs
|
||||
ansible.builtin.command:
|
||||
cmd: "getent ahostsv4 {{ item }} | awk '{print $1; exit}'"
|
||||
register: proxy_resolution
|
||||
loop: "{{ proxy_hostnames }}"
|
||||
changed_when: false
|
||||
failed_when: proxy_resolution.stdout == ""
|
||||
|
||||
- name: Set proxy IP list
|
||||
ansible.builtin.set_fact:
|
||||
proxy_ips: "{{ proxy_resolution.results | map(attribute='stdout') | list }}"
|
||||
|
||||
- name: Block Koji HTTP from proxies
|
||||
when: koji_action == 'block'
|
||||
block:
|
||||
- name: Ensure nftables table exists
|
||||
ansible.builtin.command:
|
||||
cmd: "nft add table {{ nft_table }}"
|
||||
register: nft_table_add
|
||||
changed_when: nft_table_add.rc == 0
|
||||
failed_when: nft_table_add.rc != 0 and 'File exists' not in nft_table_add.stderr
|
||||
|
||||
- name: Ensure nftables chain exists
|
||||
ansible.builtin.command:
|
||||
cmd: "nft add chain {{ nft_table }} {{ nft_chain }} '{ type filter hook input priority 0; policy accept; }'"
|
||||
register: nft_chain_add
|
||||
changed_when: nft_chain_add.rc == 0
|
||||
failed_when: nft_chain_add.rc != 0 and 'File exists' not in nft_chain_add.stderr
|
||||
|
||||
- name: Ensure nftables set exists
|
||||
ansible.builtin.command:
|
||||
cmd: "nft add set {{ nft_table }} {{ nft_set }} '{ type ipv4_addr; comment \"{{ nft_comment }}\"; }'"
|
||||
register: nft_set_add
|
||||
changed_when: nft_set_add.rc == 0
|
||||
failed_when: nft_set_add.rc != 0 and 'File exists' not in nft_set_add.stderr
|
||||
|
||||
- name: Ensure drop rule exists
|
||||
ansible.builtin.command:
|
||||
cmd: "nft add rule {{ nft_table }} {{ nft_chain }} tcp dport {{ koji_http_port }} ip saddr @{{ nft_set }} drop comment \"{{ nft_comment }}\""
|
||||
register: nft_rule_add
|
||||
changed_when: nft_rule_add.rc == 0
|
||||
failed_when: nft_rule_add.rc != 0 and 'File exists' not in nft_rule_add.stderr
|
||||
|
||||
- name: Add proxy IPs to nftables set
|
||||
ansible.builtin.command:
|
||||
cmd: "nft add element {{ nft_table }} {{ nft_set }} '{ {{ proxy_ips | join(', ') }} }'"
|
||||
register: nft_add_elements
|
||||
changed_when: nft_add_elements.rc == 0
|
||||
failed_when: nft_add_elements.rc != 0 and 'File exists' not in nft_add_elements.stderr
|
||||
|
||||
- name: Report block action
|
||||
ansible.builtin.debug:
|
||||
msg: "Blocked tcp/{{ koji_http_port }} from {{ proxy_ips | join(', ') }}"
|
||||
|
||||
- name: Unblock Koji HTTP from proxies
|
||||
when: koji_action == 'unblock'
|
||||
block:
|
||||
- name: Flush nftables set (if present)
|
||||
ansible.builtin.command:
|
||||
cmd: "nft flush set {{ nft_table }} {{ nft_set }}"
|
||||
register: nft_set_flush
|
||||
changed_when: nft_set_flush.rc == 0
|
||||
failed_when: nft_set_flush.rc != 0 and 'No such file or directory' not in nft_set_flush.stderr
|
||||
|
||||
- name: Find drop rule handle
|
||||
ansible.builtin.shell:
|
||||
cmd: set -o pipefail && nft -a list chain {{ nft_table }} {{ nft_chain }} | awk '/tcp dport {{ koji_http_port }}.* @{{ nft_set }}.* drop/ {print $NF}'
|
||||
register: rule_handle
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Delete drop rule by handle
|
||||
ansible.builtin.command:
|
||||
cmd: "nft delete rule {{ nft_table }} {{ nft_chain }} handle {{ rule_handle.stdout }}"
|
||||
when: rule_handle.stdout != ""
|
||||
|
||||
- name: Report unblock action
|
||||
ansible.builtin.debug:
|
||||
msg: "Unblocked tcp/{{ koji_http_port }}"
|
||||
|
||||
- name: Show current nftables status
|
||||
when: koji_action == 'status'
|
||||
block:
|
||||
- name: Show table
|
||||
ansible.builtin.command:
|
||||
cmd: "nft list table {{ nft_table }}"
|
||||
register: table_status
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Show set
|
||||
ansible.builtin.command:
|
||||
cmd: "nft list set {{ nft_table }} {{ nft_set }}"
|
||||
register: set_status
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Report status
|
||||
ansible.builtin.debug:
|
||||
msg: |
|
||||
{{ table_status.stdout if table_status.rc == 0 else '(no table)' }}
|
||||
{{ set_status.stdout if set_status.rc == 0 else '(no set)' }}
|
||||
Loading…
Add table
Add a link
Reference in a new issue