diff --git a/roles/bootstrap/handlers/proftpd.yml b/roles/bootstrap/handlers/proftpd.yml index b890fc0..02728a7 100644 --- a/roles/bootstrap/handlers/proftpd.yml +++ b/roles/bootstrap/handlers/proftpd.yml @@ -6,17 +6,25 @@ become: true block: - name: Create ProFTPd non-web user subdirectories + when: "'ftps' in item[0]['services'] and not 'caddy' in item[1]['services'] and not 'httpd' in item[1]['services'] and not 'www-data' in item[1]['services'] and not 'http' in item[1]['services'] and not 'https' in item[1]['services']" ansible.builtin.file: - follow: true + # follow: true force: true - group: "{{ item.value.chown.split(':')[0] }}" - owner: "{{ item.value.chown.split(':')[1] }}" - path: "{{ item.value.chroot }}" + owner: "{{ item[0]['username'] }}" + group: "{{ item[0]['group'] | default(item[0]['username']) }}" + path: "{{ item[0]['home'] | default('/home/' ~ item[0]['username']) }}/{{ item[1]['username'] }}" state: directory - loop: "{{ lookup('ansible.builtin.dict', config.proftpd.vusers) }}" - # @TODO complete below commented out tasks - # - name: Provide TLS/SSL resources for FTPS capabilities with ProFTPd - # - name: Load prerequisite modules for intended configuration + loop: "{{ hostvars[inventory_hostname]['users'].values() | product(config['proftpd']['vusers'].values()) }}" + - name: Create ProFTPd FTP public directory for anonymous logins + when: "'ftps' in item.value['services']" + ansible.builtin.file: + # follow: true + force: true + owner: "{{ item.value['username'] }}" + group: "{{ item.value['group'] | default(item.value['username']) }}" + path: "{{ item.value['home'] | default('/home/' ~ item.value['username']) }}/public" + state: directory + loop: "{{ lookup('ansible.builtin.dict', hostvars[inventory_hostname]['users']) }}" - name: Configure ProFTPd main control server ansible.builtin.template: backup: true @@ -31,6 +39,7 @@ validate: proftpd --configtest vars: ftp_server_name: init + max_conns: 30 - name: Configure ProFTPd global settings ansible.builtin.template: backup: true @@ -45,25 +54,60 @@ validate: proftpd --configtest vars: pasv_ports: "49152 65534" - max_conns: 30 allow_symlinks: false + - name: Add virtual users to ProFTPd + block: + - name: Create virtual user authentication files + ansible.builtin.file: + force: true + group: root + mode: "0640" + owner: root + path: "{{ item.value }}" + state: touch + loop: "{{ lookup('ansible.builtin.dict', config['proftpd']['auth_filepaths']) }}" + - name: Create the virtual users + when: "not 'caddy' in item.value['services'] and not 'httpd' in item.value['services'] and not 'www-data' in item.value['services'] and not 'http' in item.value['services'] and not 'https' in item.value['services']" + ansible.builtin.command: + argv: + - ftpasswd + - --passwd + - "--name={{ item.value['username'] }}" + - "--uid=$(id -u {{ item.value['id_of'] }})" + - "--gid=$(id -g {{ item.value['gid_of'] }})" + - "--home={{ hostvars[inventory_hostname]['users']['ftp']['home'] | default('/srv/ftp') }}/{{ item.value['username'] }}" + - --shell=/sbin/nologin + - --file={{ config['proftpd']['auth_filepaths']['users_path'] }} + - --stdin + stdin: "{{ item.value['password'] }}" + loop: "{{ lookup('ansible.builtin.dict', config['proftpd']['vusers']) }}" + - name: Create the virtual groups of virtual users + when: "not 'caddy' in item.value['services'] and not 'httpd' in item.value['services'] and not 'www-data' in item.value['services'] and not 'http' in item.value['services'] and not 'https' in item.value['services']" + ansible.builtin.command: + argv: + - ftpasswd + - --group + - "--name={{ item.value['username'] }}" + - "--gid=$(id -g {{ item.value['gid_of'] }})" + - "--member={{ item.value['username'] }}" + - --file={{ config['proftpd']['auth_filepaths']['groups_path'] }} + loop: "{{ lookup('ansible.builtin.dict', config['proftpd']['vusers']) }}" + # @TODO create tasks in block integrating LDAP users to ProFTPd + # - name: Integrate LDAP users into ProFTPd - name: Create ProFTPd FTPS virtual host ansible.builtin.template: backup: true comment_end_string: "#}" comment_start_string: "{#" - dest: "/etc/proftpd/conf.d/{{ config.proftpd.name.lowercase() }}.conf" + dest: "/etc/proftpd/conf.d/{{ config['proftpd']['name'].lowercase() }}.conf" follow: true force: true group: root owner: root - src: proftpd/conf.d/vhost@vps1.conf.j2 + src: "proftpd/conf.d/vhost@vps1-{{ hostvars[inventory_hostname].fqdn }}.conf.j2" validate: proftpd --configtest vars: - ftp_server_name: "{{ config.proftpd.name.uppercase() }}'s Archive'" - # @TODO finish constructing below block task - # - name: Add virtual users to ProFTPd FTPS virtual host - # block: - # - name: Create the virtual users - # - name: Specify what virtual users are allowed login - # - name: Specify restrictions for virtual users on the directories they will reside in + ftp_server_name: "{{ config['proftpd']['name'].uppercase() }}'s Archive'" + allowed_users: "{{ ','.join(list(map(lambda u: u['username'], filter(lambda u: not 'http' in u['services'] and not 'https' in u['services'] and not 'httpd' in u['services'] and not 'caddy' in u['services'] and not 'www-data' in u['services'], config['proftpd']['vusers'].values())))) }}" + anon_root: "{{ map(lambda u: u['home'], filter(lambda u: 'ftps' in u['services'] or 'proftpd' in u['services'], hostvars[inventory_hostname]['users'].values())) | list | random }}/public" + anon_user: "{{ config['proftpd']['vusers']['smuggler']['username'] }}"